From 5fd83771641d15c418f747bd343ba6738d3875f7 Mon Sep 17 00:00:00 2001 From: Cameron Katri Date: Sun, 9 May 2021 14:20:58 -0400 Subject: Import macOS userland adv_cmds-176 basic_cmds-55 bootstrap_cmds-116.100.1 developer_cmds-66 diskdev_cmds-667.40.1 doc_cmds-53.60.1 file_cmds-321.40.3 mail_cmds-35 misc_cmds-34 network_cmds-606.40.1 patch_cmds-17 remote_cmds-63 shell_cmds-216.60.1 system_cmds-880.60.2 text_cmds-106 --- developer_cmds/asa/asa.1 | 85 ++ developer_cmds/asa/asa.c | 131 +++ developer_cmds/ctags/C.c | 555 +++++++++ developer_cmds/ctags/ctags.1 | 221 ++++ developer_cmds/ctags/ctags.c | 282 +++++ developer_cmds/ctags/ctags.h | 92 ++ developer_cmds/ctags/fortran.c | 175 +++ developer_cmds/ctags/lisp.c | 112 ++ developer_cmds/ctags/print.c | 122 ++ developer_cmds/ctags/test/ctags.test | 69 ++ developer_cmds/ctags/tree.c | 142 +++ developer_cmds/ctags/yacc.c | 158 +++ .../developer_cmds.xcodeproj/project.pbxproj | 787 +++++++++++++ .../project.xcworkspace/contents.xcworkspacedata | 7 + developer_cmds/indent/args.c | 327 ++++++ developer_cmds/indent/indent.1 | 559 +++++++++ developer_cmds/indent/indent.c | 1234 +++++++++++++++++++ developer_cmds/indent/indent.h | 47 + developer_cmds/indent/indent_codes.h | 70 ++ developer_cmds/indent/indent_globs.h | 329 ++++++ developer_cmds/indent/io.c | 667 +++++++++++ developer_cmds/indent/lexi.c | 608 ++++++++++ developer_cmds/indent/parse.c | 332 ++++++ developer_cmds/indent/pr_comment.c | 429 +++++++ developer_cmds/lorder/lorder.1 | 75 ++ developer_cmds/lorder/lorder.sh | 104 ++ developer_cmds/rpcgen/rpc_clntout.c | 230 ++++ developer_cmds/rpcgen/rpc_cout.c | 741 ++++++++++++ developer_cmds/rpcgen/rpc_hout.c | 534 +++++++++ developer_cmds/rpcgen/rpc_main.c | 1170 +++++++++++++++++++ developer_cmds/rpcgen/rpc_parse.c | 643 ++++++++++ developer_cmds/rpcgen/rpc_parse.h | 168 +++ developer_cmds/rpcgen/rpc_sample.c | 261 +++++ developer_cmds/rpcgen/rpc_scan.c | 521 +++++++++ developer_cmds/rpcgen/rpc_scan.h | 104 ++ developer_cmds/rpcgen/rpc_svcout.c | 980 ++++++++++++++++ developer_cmds/rpcgen/rpc_tblout.c | 179 +++ developer_cmds/rpcgen/rpc_util.c | 513 ++++++++ developer_cmds/rpcgen/rpc_util.h | 178 +++ developer_cmds/rpcgen/rpcgen.1 | 452 +++++++ developer_cmds/unifdef/unifdef.1 | 415 +++++++ developer_cmds/unifdef/unifdef.c | 1235 ++++++++++++++++++++ developer_cmds/unifdef/unifdefall.sh | 79 ++ developer_cmds/xcodescripts/install-lorder.sh | 7 + developer_cmds/xcodescripts/install-unifdefall.sh | 9 + 45 files changed, 16138 insertions(+) create mode 100644 developer_cmds/asa/asa.1 create mode 100644 developer_cmds/asa/asa.c create mode 100644 developer_cmds/ctags/C.c create mode 100644 developer_cmds/ctags/ctags.1 create mode 100644 developer_cmds/ctags/ctags.c create mode 100644 developer_cmds/ctags/ctags.h create mode 100644 developer_cmds/ctags/fortran.c create mode 100644 developer_cmds/ctags/lisp.c create mode 100644 developer_cmds/ctags/print.c create mode 100644 developer_cmds/ctags/test/ctags.test create mode 100644 developer_cmds/ctags/tree.c create mode 100644 developer_cmds/ctags/yacc.c create mode 100644 developer_cmds/developer_cmds.xcodeproj/project.pbxproj create mode 100644 developer_cmds/developer_cmds.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 developer_cmds/indent/args.c create mode 100644 developer_cmds/indent/indent.1 create mode 100644 developer_cmds/indent/indent.c create mode 100644 developer_cmds/indent/indent.h create mode 100644 developer_cmds/indent/indent_codes.h create mode 100644 developer_cmds/indent/indent_globs.h create mode 100644 developer_cmds/indent/io.c create mode 100644 developer_cmds/indent/lexi.c create mode 100644 developer_cmds/indent/parse.c create mode 100644 developer_cmds/indent/pr_comment.c create mode 100644 developer_cmds/lorder/lorder.1 create mode 100644 developer_cmds/lorder/lorder.sh create mode 100644 developer_cmds/rpcgen/rpc_clntout.c create mode 100644 developer_cmds/rpcgen/rpc_cout.c create mode 100644 developer_cmds/rpcgen/rpc_hout.c create mode 100644 developer_cmds/rpcgen/rpc_main.c create mode 100644 developer_cmds/rpcgen/rpc_parse.c create mode 100644 developer_cmds/rpcgen/rpc_parse.h create mode 100644 developer_cmds/rpcgen/rpc_sample.c create mode 100644 developer_cmds/rpcgen/rpc_scan.c create mode 100644 developer_cmds/rpcgen/rpc_scan.h create mode 100644 developer_cmds/rpcgen/rpc_svcout.c create mode 100644 developer_cmds/rpcgen/rpc_tblout.c create mode 100644 developer_cmds/rpcgen/rpc_util.c create mode 100644 developer_cmds/rpcgen/rpc_util.h create mode 100644 developer_cmds/rpcgen/rpcgen.1 create mode 100644 developer_cmds/unifdef/unifdef.1 create mode 100644 developer_cmds/unifdef/unifdef.c create mode 100644 developer_cmds/unifdef/unifdefall.sh create mode 100644 developer_cmds/xcodescripts/install-lorder.sh create mode 100644 developer_cmds/xcodescripts/install-unifdefall.sh (limited to 'developer_cmds') diff --git a/developer_cmds/asa/asa.1 b/developer_cmds/asa/asa.1 new file mode 100644 index 0000000..4c388a0 --- /dev/null +++ b/developer_cmds/asa/asa.1 @@ -0,0 +1,85 @@ +.\" $NetBSD: asa.1,v 1.5 1997/09/20 14:55:00 lukem Exp $ +.\" +.\" Copyright (c) 1993 Winning Strategies, Inc. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by Winning Strategies, Inc. +.\" 4. The name of the author may not be used to endorse or promote products +.\" derived from this software without specific prior written permission +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.Dd September 23, 1993 +.Dt ASA 1 +.Os +.Sh NAME +.Nm asa +.Nd interpret carriage-control characters. +.Sh SYNOPSIS +.Nm +.Op Ar +.Sh DESCRIPTION +The +.Nm +utility reads files sequentially, mapping +.Tn FORTRAN +carriage-control characters to line-printer control sequences, +and writes them to the standard output. +.Pp +The first character of each line is interpreted as a carriage-control +character. The following characters are interpreted as follows: +.Bl -tag -width "" +.It +Output the rest of the line without change. +.It 0 +Output a character before printing the rest of the line. +.It 1 +Output a character before printing the rest of the line. +.It + +The trailing of the previous line is replaced by a +before printing the rest of the line. +.El +.Pp +Lines beginning with characters other than the above are treated as if they +begin with . +.Sh EXAMPLES +To view a file containing the output of a +.Tn FORTRAN program: +.Dl asa file +.Pp +To format the output of a +.Tn FORTRAN +program and redirect it to a line-printer. +.Dl a.out | asa | lpr +.Sh DIAGNOSTICS +The +.Nm +utility exit 0 on success, and >0 if an error occurs. +.Sh SEE ALSO +.Xr f77 1 +.Sh STANDARDS +The +.Nm +utility conforms to +.St -p1003.2-92 . +.Sh AUTHORS +J.T. Conklin, Winning Strategies, Inc. diff --git a/developer_cmds/asa/asa.c b/developer_cmds/asa/asa.c new file mode 100644 index 0000000..9516a45 --- /dev/null +++ b/developer_cmds/asa/asa.c @@ -0,0 +1,131 @@ +/* $NetBSD: asa.c,v 1.11 1997/09/20 14:55:00 lukem Exp $ */ + +/* + * Copyright (c) 1993,94 Winning Strategies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Winning Strategies, Inc. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#ifndef lint +__RCSID("$NetBSD: asa.c,v 1.11 1997/09/20 14:55:00 lukem Exp $"); +#endif + +#include +#include +#include +#include + +static void asa __P((FILE *)); +int main __P((int, char *[])); + +int main(int argc, char **argv) +{ + FILE *fp; + int exit_val = 0; + /* skip progname */ + argv++; + + if (*argv && !strcmp(*argv, "--")) { + argv++; + argc--; + } + + if (argc == 1) { + asa(stdin); + exit(exit_val); + } + + do { + if (*argv) { + if (!(fp = fopen(*argv, "r"))) { + warn ("%s", *argv); + exit_val = 1; + continue; + } else { + asa(fp); + (void)fclose(fp); + } + } + } while (*argv++); + + exit (exit_val); +} + +static void +asa(f) + FILE *f; +{ + char *buf; + size_t len; + + if ((buf = fgetln (f, &len)) != NULL) { + if (buf[len - 1] == '\n') + buf[--len] = '\0'; + /* special case the first line */ + switch (buf[0]) { + case '0': + putchar ('\n'); + break; + case '1': + putchar ('\f'); + break; + } + + if (len > 1 && buf[0] && buf[1]) { + printf("%.*s", (int)(len - 1), buf + 1); + } + + while ((buf = fgetln(f, &len)) != NULL) { + if (buf[len - 1] == '\n') + buf[--len] = '\0'; + switch (buf[0]) { + default: + case ' ': + putchar ('\n'); + break; + case '0': + putchar ('\n'); + putchar ('\n'); + break; + case '1': + putchar ('\n'); + putchar ('\f'); + break; + case '+': + putchar ('\r'); + break; + } + + if (len > 1 && buf[0] && buf[1]) { + printf("%.*s", (int)(len - 1), buf + 1); + } + } + + putchar ('\n'); + } +} diff --git a/developer_cmds/ctags/C.c b/developer_cmds/ctags/C.c new file mode 100644 index 0000000..c99d617 --- /dev/null +++ b/developer_cmds/ctags/C.c @@ -0,0 +1,555 @@ +/* $NetBSD: C.c,v 1.5 1998/07/24 07:30:08 ross Exp $ */ + +/* + * Copyright (c) 1987, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)C.c 8.4 (Berkeley) 4/2/94"; +#else +__RCSID("$NetBSD: C.c,v 1.5 1998/07/24 07:30:08 ross Exp $"); +#endif +#endif /* not lint */ + +#include +#include +#include + +#include "ctags.h" + +static int func_entry __P((void)); +static void hash_entry __P((void)); +static void skip_string __P((int)); +static int str_entry __P((int)); + +/* + * c_entries -- + * read .c and .h files and call appropriate routines + */ +void +c_entries() +{ + int c; /* current character */ + int level; /* brace level */ + int token; /* if reading a token */ + int t_def; /* if reading a typedef */ + int t_level; /* typedef's brace level */ + char *sp; /* buffer pointer */ + char tok[MAXTOKEN]; /* token buffer */ + + lineftell = ftell(inf); + sp = tok; token = t_def = NO; t_level = -1; level = 0; lineno = 1; + while (GETC(!=, EOF)) { + switch (c) { + /* + * Here's where it DOESN'T handle: { + * foo(a) + * { + * #ifdef notdef + * } + * #endif + * if (a) + * puts("hello, world"); + * } + */ + case '{': + ++level; + goto endtok; + case '}': + /* + * if level goes below zero, try and fix + * it, even though we've already messed up + */ + if (--level < 0) + level = 0; + goto endtok; + + case '\n': + SETLINE; + /* + * the above 3 cases are similar in that they + * are special characters that also end tokens. + */ + endtok: if (sp > tok) { + *sp = EOS; + token = YES; + sp = tok; + } + else + token = NO; + continue; + + /* + * We ignore quoted strings and character constants + * completely. + */ + case '"': + case '\'': + (void)skip_string(c); + break; + + /* + * comments can be fun; note the state is unchanged after + * return, in case we found: + * "foo() XX comment XX { int bar; }" + */ + case '/': + if (GETC(==, '*')) { + skip_comment(); + continue; + } + (void)ungetc(c, inf); + c = '/'; + goto storec; + + /* hash marks flag #define's. */ + case '#': + if (sp == tok) { + hash_entry(); + break; + } + goto storec; + + /* + * if we have a current token, parenthesis on + * level zero indicates a function. + */ + case '(': + if (!level && token) { + int curline; + + if (sp != tok) + *sp = EOS; + /* + * grab the line immediately, we may + * already be wrong, for example, + * foo\n + * (arg1, + */ + ct_getline(); + curline = lineno; + if (func_entry()) { + ++level; + pfnote(tok, curline); + } + break; + } + goto storec; + + /* + * semi-colons indicate the end of a typedef; if we find a + * typedef we search for the next semi-colon of the same + * level as the typedef. Ignoring "structs", they are + * tricky, since you can find: + * + * "typedef long time_t;" + * "typedef unsigned int u_int;" + * "typedef unsigned int u_int [10];" + * + * If looking at a typedef, we save a copy of the last token + * found. Then, when we find the ';' we take the current + * token if it starts with a valid token name, else we take + * the one we saved. There's probably some reasonable + * alternative to this... + */ + case ';': + if (t_def && level == t_level) { + t_def = NO; + ct_getline(); + if (sp != tok) + *sp = EOS; + pfnote(tok, lineno); + break; + } + goto storec; + + /* + * store characters until one that can't be part of a token + * comes along; check the current token against certain + * reserved words. + */ + default: + storec: if (!intoken(c)) { + if (sp == tok) + break; + *sp = EOS; + if (tflag) { + /* no typedefs inside typedefs */ + if (!t_def && + !memcmp(tok, "typedef",8)) { + t_def = YES; + t_level = level; + break; + } + /* catch "typedef struct" */ + if ((!t_def || t_level < level) + && (!memcmp(tok, "struct", 7) + || !memcmp(tok, "union", 6) + || !memcmp(tok, "enum", 5))) { + /* + * get line immediately; + * may change before '{' + */ + ct_getline(); + if (str_entry(c)) + ++level; + break; + /* } */ + } + } + sp = tok; + } + else if (sp != tok || begtoken(c)) { + *sp++ = c; + token = YES; + } + continue; + } + + sp = tok; + token = NO; + } +} + +/* + * func_entry -- + * handle a function reference + */ +static int +func_entry() +{ + int c; /* current character */ + int level = 0; /* for matching '()' */ + static char attribute[] = "__attribute__"; + char maybe_attribute[sizeof attribute + 1], + *anext; + + /* + * Find the end of the assumed function declaration. + * Note that ANSI C functions can have type definitions so keep + * track of the parentheses nesting level. + */ + while (GETC(!=, EOF)) { + switch (c) { + case '\'': + case '"': + /* skip strings and character constants */ + skip_string(c); + break; + case '/': + /* skip comments */ + if (GETC(==, '*')) + skip_comment(); + break; + case '(': + level++; + break; + case ')': + if (level == 0) + goto fnd; + level--; + break; + case '\n': + SETLINE; + } + } + return (NO); +fnd: + /* + * we assume that the character after a function's right paren + * is a token character if it's a function and a non-token + * character if it's a declaration. Comments don't count... + */ + for (anext = maybe_attribute;;) { + while (GETC(!=, EOF) && iswhite(c)) + if (c == '\n') + SETLINE; + if (c == EOF) + return NO; + /* + * Recognize the gnu __attribute__ extension, which would + * otherwise make the heuristic test DTWT + */ + if (anext == maybe_attribute) { + if (intoken(c)) { + *anext++ = c; + continue; + } + } else { + if (intoken(c)) { + if (anext - maybe_attribute + < (int)(sizeof attribute - 1)) + *anext++ = c; + else break; + continue; + } else { + *anext++ = '\0'; + if (strcmp(maybe_attribute, attribute) == 0) { + (void)ungetc(c, inf); + return NO; + } + break; + } + } + if (intoken(c) || c == '{') + break; + if (c == '/' && GETC(==, '*')) + skip_comment(); + else { /* don't ever "read" '/' */ + (void)ungetc(c, inf); + return (NO); + } + } + if (c != '{') + (void)skip_key('{'); + return (YES); +} + +/* + * hash_entry -- + * handle a line starting with a '#' + */ +static void +hash_entry() +{ + int c; /* character read */ + int curline; /* line started on */ + char *sp; /* buffer pointer */ + char tok[MAXTOKEN]; /* storage buffer */ + + curline = lineno; + for (sp = tok;;) { /* get next token */ + if (GETC(==, EOF)) + return; + if (iswhite(c)) + break; + *sp++ = c; + } + *sp = EOS; + if (memcmp(tok, "define", 6)) /* only interested in #define's */ + goto skip; + for (;;) { /* this doesn't handle "#define \n" */ + if (GETC(==, EOF)) + return; + if (!iswhite(c)) + break; + } + for (sp = tok;;) { /* get next token */ + *sp++ = c; + if (GETC(==, EOF)) + return; + /* + * this is where it DOESN'T handle + * "#define \n" + */ + if (!intoken(c)) + break; + } + *sp = EOS; + if (dflag || c == '(') { /* only want macros */ + ct_getline(); + pfnote(tok, curline); + } +skip: if (c == '\n') { /* get rid of rest of define */ + SETLINE + if (*(sp - 1) != '\\') + return; + } + (void)skip_key('\n'); +} + +/* + * str_entry -- + * handle a struct, union or enum entry + */ +static int +str_entry(c) + int c; /* current character */ +{ + int curline; /* line started on */ + char *sp; /* buffer pointer */ + char tok[LINE_MAX]; /* storage buffer */ + + curline = lineno; + while (iswhite(c)) + if (GETC(==, EOF)) + return (NO); + if (c == '{') /* it was "struct {" */ + return (YES); + for (sp = tok;;) { /* get next token */ + *sp++ = c; + if (GETC(==, EOF)) + return (NO); + if (!intoken(c)) + break; + } + + switch (c) { + case '{': /* it was "struct foo{" */ + --sp; + break; + case '\n': /* it was "struct foo\n" */ + SETLINE; + if(GETC(!=, '/')) + { + while (GETC(!=, EOF)) + if (!iswhite(c)) + break; + if (c != '{') { + (void)ungetc(c, inf); + return (NO); + } + break; + } + case '/': + /* skip comments */ + if (GETC(==, '*')) { + skip_comment(); + } + /*FALLTHROUGH*/ + default: /* probably "struct foo " */ + while (GETC(!=, EOF)) + if (!iswhite(c)) + break; + if (c != '{') { + (void)ungetc(c, inf); + return (NO); + } + } + *sp = EOS; + pfnote(tok, curline); + return (YES); +} + +/* + * skip_comment -- + * skip over comment + */ +void +skip_comment() +{ + int c; /* character read */ + int star; /* '*' flag */ + + for (star = 0; GETC(!=, EOF);) + switch(c) { + /* comments don't nest, nor can they be escaped. */ + case '*': + star = YES; + break; + case '/': + if (star) + return; + break; + case '\n': + SETLINE; + /*FALLTHROUGH*/ + default: + star = NO; + break; + } +} + +/* + * skip_string -- + * skip to the end of a string or character constant. + */ +void +skip_string(key) + int key; +{ + int c, + skip; + + for (skip = NO; GETC(!=, EOF); ) + switch (c) { + case '\\': /* a backslash escapes anything */ + skip = !skip; /* we toggle in case it's "\\" */ + break; + case '\n': + SETLINE; + /*FALLTHROUGH*/ + default: + if (c == key && !skip) + return; + skip = NO; + } +} + +/* + * skip_key -- + * skip to next char "key" + */ +int +skip_key(key) + int key; +{ + int c, + skip, + retval; + + for (skip = retval = NO; GETC(!=, EOF);) + switch(c) { + case '\\': /* a backslash escapes anything */ + skip = !skip; /* we toggle in case it's "\\" */ + break; + case ';': /* special case for yacc; if one */ + case '|': /* of these chars occurs, we may */ + retval = YES; /* have moved out of the rule */ + break; /* not used by C */ + case '\'': + case '"': + /* skip strings and character constants */ + skip_string(c); + break; + case '/': + /* skip comments */ + if (GETC(==, '*')) { + skip_comment(); + break; + } + (void)ungetc(c, inf); + c = '/'; + goto norm; + case '\n': + SETLINE; + /*FALLTHROUGH*/ + default: + norm: + if (c == key && !skip) + return (retval); + skip = NO; + } + return (retval); +} diff --git a/developer_cmds/ctags/ctags.1 b/developer_cmds/ctags/ctags.1 new file mode 100644 index 0000000..353c990 --- /dev/null +++ b/developer_cmds/ctags/ctags.1 @@ -0,0 +1,221 @@ +.\" $NetBSD: ctags.1,v 1.5 1997/10/18 13:18:24 lukem Exp $ +.\" +.\" Copyright (c) 1987, 1990, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)ctags.1 8.1 (Berkeley) 6/6/93 +.\" +.Dd June 6, 1993 +.Dt CTAGS 1 +.Os BSD 4 +.Sh NAME +.Nm ctags +.Nd create a tags file +.Sh SYNOPSIS +.Nm +.Op Fl BFadtuwvx +.Op Fl f Ar tags_file +.Ar name ... +.Sh DESCRIPTION +.Nm +makes a tags file for +.Xr ex 1 +from the specified C, +Pascal, Fortran, +.Tn YACC , +lex, and lisp sources. +A tags file gives the locations of specified objects in a group of files. +Each line of the tags file contains the object name, the file in which it +is defined, and a search pattern for the object definition, separated by +white-space. +.Pp +Using the +.Ar tags +file, +.Xr ex 1 +can quickly locate these object definitions. +Depending upon the options provided to +.Nm , +objects will consist of subroutines, typedefs, defines, structs, +enums, and unions. +.Bl -tag -width Ds +.It Fl a +append to +.Ar tags +file. +.It Fl B +use backward searching patterns +.Pq Li ?...? . +.It Fl d +create tags for +.Li #defines +that don't take arguments; +.Li #defines +that take arguments are tagged automatically. +.It Fl F +use forward searching patterns +.Pq Li /.../ +(the default). +.It Fl f +Places the tag descriptions in a file called +.Ar tags_file . +The default behavior is to place them in a file called +.Ar tags . +.It Fl t +create tags for typedefs, structs, unions, and enums. +.It Fl u +update the specified files in the +.Ar tags +file, that is, all +references to them are deleted, and the new values are appended to the +file. (Beware: this option is implemented in a way which is rather +slow; it is usually faster to simply rebuild the +.Ar tags +file.) +.It Fl v +An index of the form expected by +.Xr vgrind 1 +is produced on the standard output. This listing +contains the object name, file name, and page number (assuming 64-line pages). +Because the output will be sorted into lexicographic order, +it may be desirable to run the output through +.Xr sort 1 . +Sample use: +.Bd -literal -offset indent +ctags \-v files \&| sort \-f > index +vgrind \-x index +.Ed +.It Fl w +suppress warning diagnostics. +.It Fl x +.Nm +produces a list of object +names, the line number and file name on which each is defined, as well +as the text of that line and prints this on the standard output. This +is a simple function index which can be printed out for reading off-line. +.El +.Pp +Files whose names end in +.Sq \&.c +or +.Sq \&.h +are assumed to be C +source files and are searched for C style routine and macro definitions. +Files whose names end in +.Sq \&.y +are assumed to be +.Tn YACC +source files. +Files whose names end in +.Sq \&.l +are assumed to be lisp files if their +first non-blank character is `;', `(', or `[', +otherwise, they are treated +as lex files. Other files are first examined to see if they +contain any Pascal or Fortran routine definitions; if not, they are +searched for C-style definitions. +.Pp +The tag +.Li main +is treated specially in C programs. The tag formed +is created by prepending +.Ar M +to the name of the file, with the +trailing +.Sq \&.c +and any leading pathname components removed. This +makes use of +.Nm +practical in directories with more than one +program. +.Pp +Yacc and lex files each have a special tag. +.Ar Yyparse +is the start +of the second section of the yacc file, and +.Ar yylex +is the start of +the second section of the lex file. +.Sh FILES +.Bl -tag -width tagsxxx -compact +.It Pa tags +default output tags file +.El +.Sh DIAGNOSTICS +.Nm +exits with a value of 1 if an error occurred, 0 otherwise. +Duplicate objects are not considered to be errors. +.Sh SEE ALSO +.Xr cc 1 , +.Xr ex 1 , +.Xr lex 1 , +.Xr sort 1 , +.\" .Xr vgrind 1 , +.Xr vi 1 , +.Xr yacc 1 +.Sh BUGS +Recognition of +.Em functions , +.Em subroutines , +and +.Em procedures +for +.Tn FORTRAN +and Pascal is done in a very simple-minded way. No attempt +is made to deal with block structure; if you have Pascal procedures +with the same name in different blocks, you lose. +.Nm +doesn't +understand about Pascal types. +.Pp +The method of deciding whether to look for C, Pascal, or +.Tn FORTRAN +functions is a hack. +.Pp +.Nm +relies on the input being well formed, so any syntactical +errors will completely confuse it. It also finds some legal syntax +to be confusing; for example, because it doesn't understand +.Li #ifdef Ns 's +(incidentally, that's a feature, not a bug), any code with unbalanced +braces inside +.Li #ifdef Ns 's +will cause it to become somewhat disoriented. +In a similar fashion, multiple line changes within a definition will +cause it to enter the last line of the object, rather than the first, as +the searching pattern. The last line of multiple line +.Li typedef Ns 's +will similarly be noted. +.Sh HISTORY +The +.Nm +command appeared in +.Bx 3.0 . diff --git a/developer_cmds/ctags/ctags.c b/developer_cmds/ctags/ctags.c new file mode 100644 index 0000000..490f91d --- /dev/null +++ b/developer_cmds/ctags/ctags.c @@ -0,0 +1,282 @@ +/* $NetBSD: ctags.c,v 1.6 1998/08/25 20:59:36 ross Exp $ */ + +/* + * Copyright (c) 1987, 1993, 1994, 1995 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#ifndef lint +__COPYRIGHT("@(#) Copyright (c) 1987, 1993, 1994, 1995\n\ + The Regents of the University of California. All rights reserved.\n"); +#endif /* not lint */ + +#ifndef lint +#if 0 +static char sccsid[] = "@(#)ctags.c 8.4 (Berkeley) 2/7/95"; +#endif +__RCSID("$NetBSD: ctags.c,v 1.6 1998/08/25 20:59:36 ross Exp $"); +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include + +#include "ctags.h" + +/* + * ctags: create a tags file + */ + +NODE *head; /* head of the sorted binary tree */ + + /* boolean "func" (see init()) */ +bool _wht[256], _etk[256], _itk[256], _btk[256], _gd[256]; + +FILE *inf; /* ioptr for current input file */ +FILE *outf; /* ioptr for tags file */ + +long lineftell; /* ftell after getc( inf ) == '\n' */ + +int lineno; /* line number of current line */ +int dflag; /* -d: non-macro defines */ +int tflag=1; /* -t: create tags for typedefs */ +int vflag; /* -v: vgrind style index output */ +int wflag; /* -w: suppress warnings */ +int xflag; /* -x: cxref style output */ + +char *curfile; /* current input file name */ +char searchar = '/'; /* use /.../ searches by default */ +char lbuf[LINE_MAX]; + +void init __P((void)); +int main __P((int, char **)); +void find_entries __P((char *)); + +int +main(argc, argv) + int argc; + char **argv; +{ + static char *outfile = "tags"; /* output file */ + int aflag; /* -a: append to tags */ + int uflag; /* -u: update tags */ + int exit_val; /* exit value */ + int step; /* step through args */ + int ch; /* getopts char */ + char cmd[100]; /* too ugly to explain */ + + aflag = uflag = NO; + while ((ch = getopt(argc, argv, "BFadf:tuwvx")) != -1) + switch(ch) { + case 'B': + searchar = '?'; + break; + case 'F': + searchar = '/'; + break; + case 'a': + aflag++; + break; + case 'd': + dflag++; + break; + case 'f': + outfile = optarg; + break; + case 't': + tflag++; + break; + case 'T': + tflag--; + break; + case 'u': + uflag++; + break; + case 'w': + wflag++; + break; + case 'v': + vflag++; + case 'x': + xflag++; + break; + case '?': + default: + goto usage; + } + argv += optind; + argc -= optind; + if (!argc) { +usage: (void)fprintf(stderr, + "usage: ctags [-BFadtuwvx] [-f tagsfile] file ...\n"); + exit(1); + } + + init(); + + for (exit_val = step = 0; step < argc; ++step) + if (!(inf = fopen(argv[step], "r"))) { + warn("%s", argv[step]); + exit_val = 1; + } + else { + curfile = argv[step]; + find_entries(argv[step]); + (void)fclose(inf); + } + + if (head) { + if (xflag) + put_entries(head); + else { + if (uflag) { + for (step = 0; step < argc; step++) { + (void)sprintf(cmd, + "mv %s OTAGS; fgrep -v '\t%s\t' OTAGS >%s; rm OTAGS", + outfile, argv[step], + outfile); + system(cmd); + } + ++aflag; + } + if (!(outf = fopen(outfile, aflag ? "a" : "w"))) + err(exit_val ? exit_val : 1, "%s", outfile); + put_entries(head); + (void)fclose(outf); + if (uflag) { + (void)sprintf(cmd, "sort -o %s %s", + outfile, outfile); + system(cmd); + } + } + } + exit(exit_val); +} + +/* + * init -- + * this routine sets up the boolean psuedo-functions which work by + * setting boolean flags dependent upon the corresponding character. + * Every char which is NOT in that string is false with respect to + * the pseudo-function. Therefore, all of the array "_wht" is NO + * by default and then the elements subscripted by the chars in + * CWHITE are set to YES. Thus, "_wht" of a char is YES if it is in + * the string CWHITE, else NO. + */ +void +init() +{ + int i; + unsigned char *sp; + + for (i = 0; i < 256; i++) { + _wht[i] = _etk[i] = _itk[i] = _btk[i] = NO; + _gd[i] = YES; + } +#define CWHITE (unsigned char *)" \f\t\n" + for (sp = CWHITE; *sp; sp++) /* white space chars */ + _wht[*sp] = YES; +#define CTOKEN (unsigned char *)" \t\n\"'#()[]{}=-+%*/&|^~!<>;,.:?" + for (sp = CTOKEN; *sp; sp++) /* token ending chars */ + _etk[*sp] = YES; +#define CINTOK (unsigned char *)"ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz0123456789" + for (sp = CINTOK; *sp; sp++) /* valid in-token chars */ + _itk[*sp] = YES; +#define CBEGIN (unsigned char *)"ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz" + for (sp = CBEGIN; *sp; sp++) /* token starting chars */ + _btk[*sp] = YES; +#define CNOTGD (unsigned char *)",;" + for (sp = CNOTGD; *sp; sp++) /* invalid after-function chars */ + _gd[*sp] = NO; +} + +/* + * find_entries -- + * this routine opens the specified file and calls the function + * which searches the file. + */ +void +find_entries(file) + char *file; +{ + char *cp; + + lineno = 0; /* should be 1 ?? KB */ + if ((cp = strrchr(file, '.')) != NULL) { + if (cp[1] == 'l' && !cp[2]) { + int c; + + for (;;) { + if (GETC(==, EOF)) + return; + if (!iswhite(c)) { + rewind(inf); + break; + } + } +#define LISPCHR ";([" +/* lisp */ if (strchr(LISPCHR, c)) { + l_entries(); + return; + } +/* lex */ else { + /* + * we search all 3 parts of a lex file + * for C references. This may be wrong. + */ + toss_yysec(); + (void)strcpy(lbuf, "%%$"); + pfnote("yylex", lineno); + rewind(inf); + } + } +/* yacc */ else if (cp[1] == 'y' && !cp[2]) { + /* + * we search only the 3rd part of a yacc file + * for C references. This may be wrong. + */ + toss_yysec(); + (void)strcpy(lbuf, "%%$"); + pfnote("yyparse", lineno); + y_entries(); + } +/* fortran */ else if ((cp[1] != 'c' && cp[1] != 'h') && !cp[2]) { + if (PF_funcs()) + return; + rewind(inf); + } + } +/* C */ c_entries(); +} diff --git a/developer_cmds/ctags/ctags.h b/developer_cmds/ctags/ctags.h new file mode 100644 index 0000000..99ba934 --- /dev/null +++ b/developer_cmds/ctags/ctags.h @@ -0,0 +1,92 @@ +/* $NetBSD: ctags.h,v 1.3 1995/03/26 20:14:07 glass Exp $ */ + +/* + * Copyright (c) 1987, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ctags.h 8.3 (Berkeley) 4/2/94 + */ + +#define bool char + +#define YES 1 +#define NO 0 +#define EOS '\0' + +#define ENDLINE 50 /* max length of pattern */ +#define MAXTOKEN 250 /* max size of single token */ + +#define SETLINE {++lineno;lineftell = ftell(inf);} +#define GETC(op,exp) ((c = getc(inf)) op (int)exp) + +#define iswhite(arg) (_wht[(unsigned)arg]) /* T if char is white */ +#define begtoken(arg) (_btk[(unsigned)arg]) /* T if char can start token */ +#define intoken(arg) (_itk[(unsigned)arg]) /* T if char can be in token */ +#define endtoken(arg) (_etk[(unsigned)arg]) /* T if char ends tokens */ +#define isgood(arg) (_gd[(unsigned)arg]) /* T if char can be after ')' */ + +typedef struct nd_st { /* sorting structure */ + struct nd_st *left, + *right; /* left and right sons */ + char *entry, /* function or type name */ + *file, /* file name */ + *pat; /* search pattern */ + int lno; /* for -x option */ + bool been_warned; /* set if noticed dup */ +} NODE; + +extern char *curfile; /* current input file name */ +extern NODE *head; /* head of the sorted binary tree */ +extern FILE *inf; /* ioptr for current input file */ +extern FILE *outf; /* ioptr for current output file */ +extern long lineftell; /* ftell after getc( inf ) == '\n' */ +extern int lineno; /* line number of current line */ +extern int dflag; /* -d: non-macro defines */ +extern int tflag; /* -t: create tags for typedefs */ +extern int vflag; /* -v: vgrind style index output */ +extern int wflag; /* -w: suppress warnings */ +extern int xflag; /* -x: cxref style output */ +extern bool _wht[], _etk[], _itk[], _btk[], _gd[]; +extern char lbuf[LINE_MAX]; +extern char *lbp; +extern char searchar; /* ex search character */ + +extern int cicmp __P((char *)); +extern void ct_getline __P((void)); +extern void pfnote __P((char *, int)); +extern int skip_key __P((int)); +extern void put_entries __P((NODE *)); +extern void toss_yysec __P((void)); +extern void l_entries __P((void)); +extern void y_entries __P((void)); +extern int PF_funcs __P((void)); +extern void c_entries __P((void)); +extern void skip_comment __P((void)); diff --git a/developer_cmds/ctags/fortran.c b/developer_cmds/ctags/fortran.c new file mode 100644 index 0000000..a4b4178 --- /dev/null +++ b/developer_cmds/ctags/fortran.c @@ -0,0 +1,175 @@ +/* $NetBSD: fortran.c,v 1.4 1997/10/18 13:18:37 lukem Exp $ */ + +/* + * Copyright (c) 1987, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)fortran.c 8.3 (Berkeley) 4/2/94"; +#else +__RCSID("$NetBSD: fortran.c,v 1.4 1997/10/18 13:18:37 lukem Exp $"); +#endif +#endif /* not lint */ + +#include +#include +#include +#include + +#include "ctags.h" + +static void takeprec __P((void)); + +char *lbp; /* line buffer pointer */ + +int +PF_funcs() +{ + bool pfcnt; /* pascal/fortran functions found */ + char *cp; + char tok[MAXTOKEN]; + + for (pfcnt = NO;;) { + lineftell = ftell(inf); + if (!fgets(lbuf, sizeof(lbuf), inf)) + return (pfcnt); + ++lineno; + lbp = lbuf; + if (*lbp == '%') /* Ratfor escape to fortran */ + ++lbp; + for (; isspace(*lbp); ++lbp) + continue; + if (!*lbp) + continue; + switch (*lbp | ' ') { /* convert to lower-case */ + case 'c': + if (cicmp("complex") || cicmp("character")) + takeprec(); + break; + case 'd': + if (cicmp("double")) { + for (; isspace(*lbp); ++lbp) + continue; + if (!*lbp) + continue; + if (cicmp("precision")) + break; + continue; + } + break; + case 'i': + if (cicmp("integer")) + takeprec(); + break; + case 'l': + if (cicmp("logical")) + takeprec(); + break; + case 'r': + if (cicmp("real")) + takeprec(); + break; + } + for (; isspace(*lbp); ++lbp) + continue; + if (!*lbp) + continue; + switch (*lbp | ' ') { + case 'f': + if (cicmp("function")) + break; + continue; + case 'p': + if (cicmp("program") || cicmp("procedure")) + break; + continue; + case 's': + if (cicmp("subroutine")) + break; + default: + continue; + } + for (; isspace(*lbp); ++lbp) + continue; + if (!*lbp) + continue; + for (cp = lbp + 1; *cp && intoken(*cp); ++cp) + continue; + if ((cp = lbp + 1) != NULL) + continue; + *cp = EOS; + (void)strcpy(tok, lbp); + ct_getline(); /* process line for ex(1) */ + pfnote(tok, lineno); + pfcnt = YES; + } + /*NOTREACHED*/ +} + +/* + * cicmp -- + * do case-independent strcmp + */ +int +cicmp(cp) + char *cp; +{ + int len; + char *bp; + + for (len = 0, bp = lbp; *cp && (*cp &~ ' ') == (*bp++ &~ ' '); + ++cp, ++len) + continue; + if (!*cp) { + lbp += len; + return (YES); + } + return (NO); +} + +static void +takeprec() +{ + for (; isspace(*lbp); ++lbp) + continue; + if (*lbp == '*') { + for (++lbp; isspace(*lbp); ++lbp) + continue; + if (!isdigit(*lbp)) + --lbp; /* force failure */ + else + while (isdigit(*++lbp)) + continue; + } +} diff --git a/developer_cmds/ctags/lisp.c b/developer_cmds/ctags/lisp.c new file mode 100644 index 0000000..e925c1b --- /dev/null +++ b/developer_cmds/ctags/lisp.c @@ -0,0 +1,112 @@ +/* $NetBSD: lisp.c,v 1.4 1997/10/18 13:18:45 lukem Exp $ */ + +/* + * Copyright (c) 1987, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)lisp.c 8.3 (Berkeley) 4/2/94"; +#else +__RCSID("$NetBSD: lisp.c,v 1.4 1997/10/18 13:18:45 lukem Exp $"); +#endif +#endif /* not lint */ + +#include +#include +#include +#include + +#include "ctags.h" + +/* + * lisp tag functions + * just look for (def or (DEF + */ +void +l_entries() +{ + int special; + char *cp; + char savedc; + char tok[MAXTOKEN]; + + for (;;) { + lineftell = ftell(inf); + if (!fgets(lbuf, sizeof(lbuf), inf)) + return; + ++lineno; + lbp = lbuf; + if (!cicmp("(def")) + continue; + special = NO; + switch(*lbp | ' ') { + case 'm': + if (cicmp("method")) + special = YES; + break; + case 'w': + if (cicmp("wrapper") || cicmp("whopper")) + special = YES; + } + for (; !isspace(*lbp); ++lbp) + continue; + for (; isspace(*lbp); ++lbp) + continue; + for (cp = lbp; *cp && *cp != '\n'; ++cp) + continue; + *cp = EOS; + if (special) { + if (!(cp = strchr(lbp, ')'))) + continue; + for (; cp >= lbp && *cp != ':'; --cp) + continue; + if (cp < lbp) + continue; + lbp = cp; + for (; *cp && *cp != ')' && *cp != ' '; ++cp) + continue; + } + else + for (cp = lbp + 1; + *cp && *cp != '(' && *cp != ' '; ++cp) + continue; + savedc = *cp; + *cp = EOS; + (void)strcpy(tok, lbp); + *cp = savedc; + ct_getline(); + pfnote(tok, lineno); + } + /*NOTREACHED*/ +} diff --git a/developer_cmds/ctags/print.c b/developer_cmds/ctags/print.c new file mode 100644 index 0000000..a6c4aaf --- /dev/null +++ b/developer_cmds/ctags/print.c @@ -0,0 +1,122 @@ +/* $NetBSD: print.c,v 1.5 1997/10/18 13:18:52 lukem Exp $ */ + +/* + * Copyright (c) 1987, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)print.c 8.3 (Berkeley) 4/2/94"; +#else +__RCSID("$NetBSD: print.c,v 1.5 1997/10/18 13:18:52 lukem Exp $"); +#endif +#endif /* not lint */ + +#include +#include +#include +#include +#include + +#include "ctags.h" + +/* + * ct_getline -- + * get the line the token of interest occurred on, + * prepare it for printing. + */ +void +ct_getline() +{ + long saveftell; + int c; + int cnt; + char *cp; + + saveftell = ftell(inf); + (void)fseek(inf, lineftell, SEEK_SET); + if (xflag) + for (cp = lbuf; GETC(!=, '\n'); *cp++ = c) + continue; + /* + * do all processing here, so we don't step through the + * line more than once; means you don't call this routine + * unless you're sure you've got a keeper. + */ + else for (cnt = 0, cp = lbuf; GETC(!=, EOF) && cnt < ENDLINE; ++cnt) { + if (c == '\\') { /* backslashes */ + if (cnt > ENDLINE - 2) + break; + *cp++ = '\\'; *cp++ = '\\'; + ++cnt; + } + else if (c == (int)searchar) { /* search character */ + if (cnt > ENDLINE - 2) + break; + *cp++ = '\\'; *cp++ = c; + ++cnt; + } + else if (c == '\n') { /* end of keep */ + *cp++ = '$'; /* can find whole line */ + break; + } + else + *cp++ = c; + } + *cp = EOS; + (void)fseek(inf, saveftell, SEEK_SET); +} + +/* + * put_entries -- + * write out the tags + */ +void +put_entries(node) + NODE *node; +{ + + if (node->left) + put_entries(node->left); + if (vflag) + printf("%s %s %d\n", + node->entry, node->file, (node->lno + 63) / 64); + else if (xflag) + printf("%-16s%4d %-16s %s\n", + node->entry, node->lno, node->file, node->pat); + else + fprintf(outf, "%s\t%s\t%c^%s%c\n", + node->entry, node->file, searchar, node->pat, searchar); + if (node->right) + put_entries(node->right); +} diff --git a/developer_cmds/ctags/test/ctags.test b/developer_cmds/ctags/test/ctags.test new file mode 100644 index 0000000..658a073 --- /dev/null +++ b/developer_cmds/ctags/test/ctags.test @@ -0,0 +1,69 @@ +/* $NetBSD: ctags.test,v 1.2 1995/03/26 20:14:14 glass Exp $ */ + +int bar = (1 + 5); + +FOO("here is a #define test: ) {"); +char sysent[20]; +int nsysent = sizeof (sysent) / sizeof (sysent[0]); +/* + * now is the time for a comment. + * four lines in length... + */struct struct_xtra{int list;};r4(x,y){};typedef struct{int bar;}struct_xxe; +#define FOO BAR +struct struct_three { + int list; +}; +#define SINGLE +int BAD(); +enum color {red, green, gold, brown}; +char qq[] = " quote(one,two) {int bar;} "; +typedef struct { + int bar; + struct struct_two { + int foo; + union union_3 { + struct struct_three entry; + char size[25]; + }; + struct last { + struct struct_three xentry; + char list[34]; + }; + }; +} struct_one; +#define TWOLINE ((MAXLIST + FUTURE + 15) \ + / (time_to_live ? 3 : 4)) +#if (defined(BAR)) +int bar; +#endif +#define MULTIPLE {\ + multiple(one,two); \ + lineno++; \ + callroute(one,two); \ +} +#if defined(BAR) +int bar; +#endif +union union_one { + struct struct_three s3; + char foo[25]; +}; +#define XYZ(A,B) (A + B / 2) * (3 - 26 + l_lineno) +routine1(one,two) /* comments here are fun... */ + struct { + int entry; + char bar[34]; + } *one; + char two[10]; +{ +typedef unsigned char u_char; + register struct buf *bp; + five(one,two); +} + routine2 (one,two) { puts("hello\n"); } + routine3 +(one, +two) { puts("world\n"); } +routine4(int one, char (*two)(void)) /* test ANSI arguments */ +{ +} diff --git a/developer_cmds/ctags/tree.c b/developer_cmds/ctags/tree.c new file mode 100644 index 0000000..c31975c --- /dev/null +++ b/developer_cmds/ctags/tree.c @@ -0,0 +1,142 @@ +/* $NetBSD: tree.c,v 1.5 1997/10/18 13:18:58 lukem Exp $ */ + +/* + * Copyright (c) 1987, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)tree.c 8.3 (Berkeley) 4/2/94"; +#else +__RCSID("$NetBSD: tree.c,v 1.5 1997/10/18 13:18:58 lukem Exp $"); +#endif +#endif /* not lint */ + +#include +#include +#include +#include +#include + +#include "ctags.h" + +static void add_node __P((NODE *, NODE *)); +static void free_tree __P((NODE *)); + +/* + * pfnote -- + * enter a new node in the tree + */ +void +pfnote(name, ln) + char *name; + int ln; +{ + NODE *np; + char *fp; + char nbuf[MAXTOKEN]; + + /*NOSTRICT*/ + if (!(np = (NODE *)malloc(sizeof(NODE)))) { + warnx("too many entries to sort"); + put_entries(head); + free_tree(head); + /*NOSTRICT*/ + if (!(head = np = (NODE *)malloc(sizeof(NODE)))) + err(1, "out of space"); + } + if (!xflag && !strcmp(name, "main")) { + if (!(fp = strrchr(curfile, '/'))) + fp = curfile; + else + ++fp; + (void)sprintf(nbuf, "M%s", fp); + fp = strrchr(nbuf, '.'); + if (fp && !fp[2]) + *fp = EOS; + name = nbuf; + } + if (!(np->entry = strdup(name))) + err(1, "strdup"); + np->file = curfile; + np->lno = ln; + np->left = np->right = 0; + if (!(np->pat = strdup(lbuf))) + err(1, "strdup"); + if (!head) + head = np; + else + add_node(np, head); +} + +static void +add_node(node, cur_node) + NODE *node, + *cur_node; +{ + int dif; + + dif = strcmp(node->entry, cur_node->entry); + if (!dif) { + if (node->file == cur_node->file) { + if (!wflag) + fprintf(stderr, "Duplicate entry in file %s, line %d: %s\nSecond entry ignored\n", node->file, lineno, node->entry); + return; + } + if (!cur_node->been_warned) + if (!wflag) + fprintf(stderr, "Duplicate entry in files %s and %s: %s (Warning only)\n", node->file, cur_node->file, node->entry); + cur_node->been_warned = YES; + } + else if (dif < 0) + if (cur_node->left) + add_node(node, cur_node->left); + else + cur_node->left = node; + else if (cur_node->right) + add_node(node, cur_node->right); + else + cur_node->right = node; +} + +static void +free_tree(node) + NODE *node; +{ + while (node) { + if (node->right) + free_tree(node->right); + free(node); + node = node->left; + } +} diff --git a/developer_cmds/ctags/yacc.c b/developer_cmds/ctags/yacc.c new file mode 100644 index 0000000..17edfa6 --- /dev/null +++ b/developer_cmds/ctags/yacc.c @@ -0,0 +1,158 @@ +/* $NetBSD: yacc.c,v 1.4 1997/10/18 13:19:04 lukem Exp $ */ + +/* + * Copyright (c) 1987, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)yacc.c 8.3 (Berkeley) 4/2/94"; +#else +__RCSID("$NetBSD: yacc.c,v 1.4 1997/10/18 13:19:04 lukem Exp $"); +#endif +#endif /* not lint */ + +#include +#include +#include +#include + +#include "ctags.h" + +/* + * y_entries: + * find the yacc tags and put them in. + */ +void +y_entries() +{ + int c; + char *sp; + bool in_rule; + char tok[MAXTOKEN]; + + in_rule = NO; + + while (GETC(!=, EOF)) + switch (c) { + case '\n': + SETLINE; + /* FALLTHROUGH */ + case ' ': + case '\f': + case '\r': + case '\t': + break; + case '{': + if (skip_key('}')) + in_rule = NO; + break; + case '\'': + case '"': + if (skip_key(c)) + in_rule = NO; + break; + case '%': + if (GETC(==, '%')) + return; + (void)ungetc(c, inf); + break; + case '/': + if (GETC(==, '*')) + skip_comment(); + else + (void)ungetc(c, inf); + break; + case '|': + case ';': + in_rule = NO; + break; + default: + if (in_rule || (!isalpha(c) && c != '.' && c != '_')) + break; + sp = tok; + *sp++ = c; + while (GETC(!=, EOF) && (intoken(c) || c == '.')) + *sp++ = c; + *sp = EOS; + ct_getline(); /* may change before ':' */ + while (iswhite(c)) { + if (c == '\n') + SETLINE; + if (GETC(==, EOF)) + return; + } + if (c == ':') { + pfnote(tok, lineno); + in_rule = YES; + } + else + (void)ungetc(c, inf); + } +} + +/* + * toss_yysec -- + * throw away lines up to the next "\n%%\n" + */ +void +toss_yysec() +{ + int c; /* read character */ + int state; + + /* + * state == 0 : waiting + * state == 1 : received a newline + * state == 2 : received first % + * state == 3 : recieved second % + */ + lineftell = ftell(inf); + for (state = 0; GETC(!=, EOF);) + switch (c) { + case '\n': + ++lineno; + lineftell = ftell(inf); + if (state == 3) /* done! */ + return; + state = 1; /* start over */ + break; + case '%': + if (state) /* if 1 or 2 */ + ++state; /* goto 3 */ + break; + default: + state = 0; /* reset */ + break; + } +} diff --git a/developer_cmds/developer_cmds.xcodeproj/project.pbxproj b/developer_cmds/developer_cmds.xcodeproj/project.pbxproj new file mode 100644 index 0000000..e43393a --- /dev/null +++ b/developer_cmds/developer_cmds.xcodeproj/project.pbxproj @@ -0,0 +1,787 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 42; + objects = { + +/* Begin PBXAggregateTarget section */ + FDA9C8500FD5E85100A6EA6E /* default */ = { + isa = PBXAggregateTarget; + buildConfigurationList = FDA9C85E0FD5E86100A6EA6E /* Build configuration list for PBXAggregateTarget "default" */; + buildPhases = ( + ); + dependencies = ( + FDA9C8590FD5E85C00A6EA6E /* PBXTargetDependency */, + FDA9C85B0FD5E85E00A6EA6E /* PBXTargetDependency */, + FDA9C8B60FD5EAA500A6EA6E /* PBXTargetDependency */, + FDA9C9870FD5F06900A6EA6E /* PBXTargetDependency */, + FDA9C8DA0FD5EBB200A6EA6E /* PBXTargetDependency */, + FDA9C8FC0FD5EC3300A6EA6E /* PBXTargetDependency */, + ); + name = default; + productName = Default; + }; + FDA9C97F0FD5F05400A6EA6E /* lorder */ = { + isa = PBXAggregateTarget; + buildConfigurationList = FDA9C98B0FD5F08700A6EA6E /* Build configuration list for PBXAggregateTarget "lorder" */; + buildPhases = ( + FDA9C97E0FD5F05400A6EA6E /* ShellScript */, + FDA9C9A20FD5F12200A6EA6E /* Install man1 */, + ); + dependencies = ( + ); + name = lorder; + productName = lorder; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + FDA9C83F0FD5E7E300A6EA6E /* asa.c in Sources */ = {isa = PBXBuildFile; fileRef = FDA9C7E40FD5D90F00A6EA6E /* asa.c */; }; + FDA9C84D0FD5E82800A6EA6E /* asa.1 in Install man1 */ = {isa = PBXBuildFile; fileRef = FDA9C7E30FD5D90F00A6EA6E /* asa.1 */; }; + FDA9C85F0FD5E87200A6EA6E /* C.c in Sources */ = {isa = PBXBuildFile; fileRef = FDA9C7E70FD5D92800A6EA6E /* C.c */; }; + FDA9C8600FD5E87200A6EA6E /* ctags.c in Sources */ = {isa = PBXBuildFile; fileRef = FDA9C7E90FD5D92800A6EA6E /* ctags.c */; }; + FDA9C8610FD5E87200A6EA6E /* fortran.c in Sources */ = {isa = PBXBuildFile; fileRef = FDA9C7EB0FD5D92800A6EA6E /* fortran.c */; }; + FDA9C8620FD5E87200A6EA6E /* lisp.c in Sources */ = {isa = PBXBuildFile; fileRef = FDA9C7EC0FD5D92800A6EA6E /* lisp.c */; }; + FDA9C8630FD5E87200A6EA6E /* print.c in Sources */ = {isa = PBXBuildFile; fileRef = FDA9C7EE0FD5D92800A6EA6E /* print.c */; }; + FDA9C8640FD5E87200A6EA6E /* tree.c in Sources */ = {isa = PBXBuildFile; fileRef = FDA9C7F10FD5D92800A6EA6E /* tree.c */; }; + FDA9C8650FD5E87200A6EA6E /* yacc.c in Sources */ = {isa = PBXBuildFile; fileRef = FDA9C7F20FD5D92800A6EA6E /* yacc.c */; }; + FDA9C86B0FD5E88900A6EA6E /* ctags.1 in Install man1 */ = {isa = PBXBuildFile; fileRef = FDA9C7E80FD5D92800A6EA6E /* ctags.1 */; }; + FDA9C8BA0FD5EAD700A6EA6E /* args.c in Sources */ = {isa = PBXBuildFile; fileRef = FDA9C7FF0FD5D92800A6EA6E /* args.c */; }; + FDA9C8BB0FD5EAD700A6EA6E /* indent.c in Sources */ = {isa = PBXBuildFile; fileRef = FDA9C8010FD5D92800A6EA6E /* indent.c */; }; + FDA9C8BC0FD5EAD700A6EA6E /* io.c in Sources */ = {isa = PBXBuildFile; fileRef = FDA9C8040FD5D92800A6EA6E /* io.c */; }; + FDA9C8BD0FD5EAD700A6EA6E /* lexi.c in Sources */ = {isa = PBXBuildFile; fileRef = FDA9C8050FD5D92800A6EA6E /* lexi.c */; }; + FDA9C8BE0FD5EAD700A6EA6E /* parse.c in Sources */ = {isa = PBXBuildFile; fileRef = FDA9C8070FD5D92800A6EA6E /* parse.c */; }; + FDA9C8BF0FD5EAD700A6EA6E /* pr_comment.c in Sources */ = {isa = PBXBuildFile; fileRef = FDA9C8080FD5D92800A6EA6E /* pr_comment.c */; }; + FDA9C8C10FD5EAEA00A6EA6E /* indent.1 in Install man1 */ = {isa = PBXBuildFile; fileRef = FDA9C8000FD5D92800A6EA6E /* indent.1 */; }; + FDA9C8DF0FD5EBE600A6EA6E /* rpc_clntout.c in Sources */ = {isa = PBXBuildFile; fileRef = FDA9C8180FD5D92800A6EA6E /* rpc_clntout.c */; }; + FDA9C8E00FD5EBE600A6EA6E /* rpc_cout.c in Sources */ = {isa = PBXBuildFile; fileRef = FDA9C8190FD5D92800A6EA6E /* rpc_cout.c */; }; + FDA9C8E10FD5EBE600A6EA6E /* rpc_hout.c in Sources */ = {isa = PBXBuildFile; fileRef = FDA9C81A0FD5D92800A6EA6E /* rpc_hout.c */; }; + FDA9C8E20FD5EBE600A6EA6E /* rpc_main.c in Sources */ = {isa = PBXBuildFile; fileRef = FDA9C81B0FD5D92800A6EA6E /* rpc_main.c */; }; + FDA9C8E30FD5EBE600A6EA6E /* rpc_parse.c in Sources */ = {isa = PBXBuildFile; fileRef = FDA9C81C0FD5D92800A6EA6E /* rpc_parse.c */; }; + FDA9C8E40FD5EBE600A6EA6E /* rpc_sample.c in Sources */ = {isa = PBXBuildFile; fileRef = FDA9C81E0FD5D92800A6EA6E /* rpc_sample.c */; }; + FDA9C8E50FD5EBE600A6EA6E /* rpc_scan.c in Sources */ = {isa = PBXBuildFile; fileRef = FDA9C81F0FD5D92800A6EA6E /* rpc_scan.c */; }; + FDA9C8E60FD5EBE600A6EA6E /* rpc_svcout.c in Sources */ = {isa = PBXBuildFile; fileRef = FDA9C8210FD5D92800A6EA6E /* rpc_svcout.c */; }; + FDA9C8E70FD5EBE600A6EA6E /* rpc_tblout.c in Sources */ = {isa = PBXBuildFile; fileRef = FDA9C8220FD5D92800A6EA6E /* rpc_tblout.c */; }; + FDA9C8E80FD5EBE600A6EA6E /* rpc_util.c in Sources */ = {isa = PBXBuildFile; fileRef = FDA9C8230FD5D92800A6EA6E /* rpc_util.c */; }; + FDA9C8EA0FD5EBF600A6EA6E /* rpcgen.1 in Install man1 */ = {isa = PBXBuildFile; fileRef = FDA9C8250FD5D92800A6EA6E /* rpcgen.1 */; }; + FDA9C9010FD5EC4800A6EA6E /* unifdef.c in Sources */ = {isa = PBXBuildFile; fileRef = FDA9C8290FD5D92800A6EA6E /* unifdef.c */; }; + FDA9C9030FD5EC5F00A6EA6E /* unifdef.1 in Install man1 */ = {isa = PBXBuildFile; fileRef = FDA9C8280FD5D92800A6EA6E /* unifdef.1 */; }; + FDA9C9900FD5F10200A6EA6E /* lorder.1 in Install man1 */ = {isa = PBXBuildFile; fileRef = FDA9C80B0FD5D92800A6EA6E /* lorder.1 */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + FDA9C8580FD5E85C00A6EA6E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = FDA9C7D70FD5D84000A6EA6E /* Project object */; + proxyType = 1; + remoteGlobalIDString = FDA9C8390FD5E7DB00A6EA6E; + remoteInfo = asa; + }; + FDA9C85A0FD5E85E00A6EA6E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = FDA9C7D70FD5D84000A6EA6E /* Project object */; + proxyType = 1; + remoteGlobalIDString = FDA9C8540FD5E85900A6EA6E; + remoteInfo = ctags; + }; + FDA9C8B50FD5EAA500A6EA6E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = FDA9C7D70FD5D84000A6EA6E /* Project object */; + proxyType = 1; + remoteGlobalIDString = FDA9C8B10FD5EAA100A6EA6E; + remoteInfo = indent; + }; + FDA9C8D90FD5EBB200A6EA6E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = FDA9C7D70FD5D84000A6EA6E /* Project object */; + proxyType = 1; + remoteGlobalIDString = FDA9C8D50FD5EBA400A6EA6E; + remoteInfo = rpcgen; + }; + FDA9C8FB0FD5EC3300A6EA6E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = FDA9C7D70FD5D84000A6EA6E /* Project object */; + proxyType = 1; + remoteGlobalIDString = FDA9C8F70FD5EC2A00A6EA6E; + remoteInfo = unifdef; + }; + FDA9C9860FD5F06900A6EA6E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = FDA9C7D70FD5D84000A6EA6E /* Project object */; + proxyType = 1; + remoteGlobalIDString = FDA9C97F0FD5F05400A6EA6E; + remoteInfo = lorder; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + FDA9C84F0FD5E82D00A6EA6E /* Install man1 */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = "$(DT_TOOLCHAIN_DIR)/usr/share/man/man1"; + dstSubfolderSpec = 0; + files = ( + FDA9C84D0FD5E82800A6EA6E /* asa.1 in Install man1 */, + ); + name = "Install man1"; + runOnlyForDeploymentPostprocessing = 1; + }; + FDA9C8730FD5E89700A6EA6E /* Install man1 */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = "$(DT_TOOLCHAIN_DIR)/usr/share/man/man1"; + dstSubfolderSpec = 0; + files = ( + FDA9C86B0FD5E88900A6EA6E /* ctags.1 in Install man1 */, + ); + name = "Install man1"; + runOnlyForDeploymentPostprocessing = 1; + }; + FDA9C8CA0FD5EAFC00A6EA6E /* Install man1 */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = "$(DT_TOOLCHAIN_DIR)/usr/share/man/man1"; + dstSubfolderSpec = 0; + files = ( + FDA9C8C10FD5EAEA00A6EA6E /* indent.1 in Install man1 */, + ); + name = "Install man1"; + runOnlyForDeploymentPostprocessing = 1; + }; + FDA9C8F40FD5EC0F00A6EA6E /* Install man1 */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = "$(DT_TOOLCHAIN_DIR)/usr/share/man/man1"; + dstSubfolderSpec = 0; + files = ( + FDA9C8EA0FD5EBF600A6EA6E /* rpcgen.1 in Install man1 */, + ); + name = "Install man1"; + runOnlyForDeploymentPostprocessing = 1; + }; + FDA9C9040FD5EC6800A6EA6E /* Install man1 */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = "$(DT_TOOLCHAIN_DIR)/usr/share/man/man1"; + dstSubfolderSpec = 0; + files = ( + FDA9C9030FD5EC5F00A6EA6E /* unifdef.1 in Install man1 */, + ); + name = "Install man1"; + runOnlyForDeploymentPostprocessing = 1; + }; + FDA9C9A20FD5F12200A6EA6E /* Install man1 */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = "$(DT_TOOLCHAIN_DIR)/usr/share/man/man1"; + dstSubfolderSpec = 0; + files = ( + FDA9C9900FD5F10200A6EA6E /* lorder.1 in Install man1 */, + ); + name = "Install man1"; + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + FDA9C7E30FD5D90F00A6EA6E /* asa.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; path = asa.1; sourceTree = ""; }; + FDA9C7E40FD5D90F00A6EA6E /* asa.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = asa.c; sourceTree = ""; }; + FDA9C7E70FD5D92800A6EA6E /* C.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = C.c; sourceTree = ""; }; + FDA9C7E80FD5D92800A6EA6E /* ctags.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; path = ctags.1; sourceTree = ""; }; + FDA9C7E90FD5D92800A6EA6E /* ctags.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ctags.c; sourceTree = ""; }; + FDA9C7EA0FD5D92800A6EA6E /* ctags.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ctags.h; sourceTree = ""; }; + FDA9C7EB0FD5D92800A6EA6E /* fortran.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fortran.c; sourceTree = ""; }; + FDA9C7EC0FD5D92800A6EA6E /* lisp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lisp.c; sourceTree = ""; }; + FDA9C7EE0FD5D92800A6EA6E /* print.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = print.c; sourceTree = ""; }; + FDA9C7F00FD5D92800A6EA6E /* ctags.test */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ctags.test; sourceTree = ""; }; + FDA9C7F10FD5D92800A6EA6E /* tree.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tree.c; sourceTree = ""; }; + FDA9C7F20FD5D92800A6EA6E /* yacc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = yacc.c; sourceTree = ""; }; + FDA9C7FF0FD5D92800A6EA6E /* args.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = args.c; sourceTree = ""; }; + FDA9C8000FD5D92800A6EA6E /* indent.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; path = indent.1; sourceTree = ""; }; + FDA9C8010FD5D92800A6EA6E /* indent.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = indent.c; sourceTree = ""; }; + FDA9C8020FD5D92800A6EA6E /* indent_codes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = indent_codes.h; sourceTree = ""; }; + FDA9C8030FD5D92800A6EA6E /* indent_globs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = indent_globs.h; sourceTree = ""; }; + FDA9C8040FD5D92800A6EA6E /* io.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = io.c; sourceTree = ""; }; + FDA9C8050FD5D92800A6EA6E /* lexi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lexi.c; sourceTree = ""; }; + FDA9C8070FD5D92800A6EA6E /* parse.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = parse.c; sourceTree = ""; }; + FDA9C8080FD5D92800A6EA6E /* pr_comment.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pr_comment.c; sourceTree = ""; }; + FDA9C8090FD5D92800A6EA6E /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = ""; }; + FDA9C80B0FD5D92800A6EA6E /* lorder.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; path = lorder.1; sourceTree = ""; }; + FDA9C80C0FD5D92800A6EA6E /* lorder.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = lorder.sh; sourceTree = ""; }; + FDA9C8180FD5D92800A6EA6E /* rpc_clntout.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rpc_clntout.c; sourceTree = ""; }; + FDA9C8190FD5D92800A6EA6E /* rpc_cout.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rpc_cout.c; sourceTree = ""; }; + FDA9C81A0FD5D92800A6EA6E /* rpc_hout.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rpc_hout.c; sourceTree = ""; }; + FDA9C81B0FD5D92800A6EA6E /* rpc_main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rpc_main.c; sourceTree = ""; }; + FDA9C81C0FD5D92800A6EA6E /* rpc_parse.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rpc_parse.c; sourceTree = ""; }; + FDA9C81D0FD5D92800A6EA6E /* rpc_parse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rpc_parse.h; sourceTree = ""; }; + FDA9C81E0FD5D92800A6EA6E /* rpc_sample.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rpc_sample.c; sourceTree = ""; }; + FDA9C81F0FD5D92800A6EA6E /* rpc_scan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rpc_scan.c; sourceTree = ""; }; + FDA9C8200FD5D92800A6EA6E /* rpc_scan.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rpc_scan.h; sourceTree = ""; }; + FDA9C8210FD5D92800A6EA6E /* rpc_svcout.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rpc_svcout.c; sourceTree = ""; }; + FDA9C8220FD5D92800A6EA6E /* rpc_tblout.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rpc_tblout.c; sourceTree = ""; }; + FDA9C8230FD5D92800A6EA6E /* rpc_util.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rpc_util.c; sourceTree = ""; }; + FDA9C8240FD5D92800A6EA6E /* rpc_util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rpc_util.h; sourceTree = ""; }; + FDA9C8250FD5D92800A6EA6E /* rpcgen.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; path = rpcgen.1; sourceTree = ""; }; + FDA9C8280FD5D92800A6EA6E /* unifdef.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; path = unifdef.1; sourceTree = ""; }; + FDA9C8290FD5D92800A6EA6E /* unifdef.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = unifdef.c; sourceTree = ""; }; + FDA9C82A0FD5D92800A6EA6E /* unifdefall.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = unifdefall.sh; sourceTree = ""; }; + FDA9C83A0FD5E7DB00A6EA6E /* asa */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = asa; sourceTree = BUILT_PRODUCTS_DIR; }; + FDA9C8550FD5E85900A6EA6E /* ctags */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ctags; sourceTree = BUILT_PRODUCTS_DIR; }; + FDA9C8B20FD5EAA100A6EA6E /* indent */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = indent; sourceTree = BUILT_PRODUCTS_DIR; }; + FDA9C8D60FD5EBA400A6EA6E /* rpcgen */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = rpcgen; sourceTree = BUILT_PRODUCTS_DIR; }; + FDA9C8F80FD5EC2A00A6EA6E /* unifdef */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = unifdef; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + FDA9C8380FD5E7DB00A6EA6E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDA9C8530FD5E85900A6EA6E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDA9C8B00FD5EAA100A6EA6E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDA9C8D40FD5EBA400A6EA6E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDA9C8F60FD5EC2A00A6EA6E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + FDA9C7D50FD5D84000A6EA6E = { + isa = PBXGroup; + children = ( + FDA9C9280FD5ED6700A6EA6E /* Source */, + FDA9C83B0FD5E7DB00A6EA6E /* Products */, + ); + sourceTree = ""; + }; + FDA9C7E20FD5D90F00A6EA6E /* asa */ = { + isa = PBXGroup; + children = ( + FDA9C7E30FD5D90F00A6EA6E /* asa.1 */, + FDA9C7E40FD5D90F00A6EA6E /* asa.c */, + ); + path = asa; + sourceTree = ""; + }; + FDA9C7E60FD5D92800A6EA6E /* ctags */ = { + isa = PBXGroup; + children = ( + FDA9C7E70FD5D92800A6EA6E /* C.c */, + FDA9C7E90FD5D92800A6EA6E /* ctags.c */, + FDA9C7EB0FD5D92800A6EA6E /* fortran.c */, + FDA9C7EC0FD5D92800A6EA6E /* lisp.c */, + FDA9C7EE0FD5D92800A6EA6E /* print.c */, + FDA9C7F10FD5D92800A6EA6E /* tree.c */, + FDA9C7F20FD5D92800A6EA6E /* yacc.c */, + FDA9C7EA0FD5D92800A6EA6E /* ctags.h */, + FDA9C7E80FD5D92800A6EA6E /* ctags.1 */, + FDA9C7EF0FD5D92800A6EA6E /* test */, + ); + path = ctags; + sourceTree = ""; + }; + FDA9C7EF0FD5D92800A6EA6E /* test */ = { + isa = PBXGroup; + children = ( + FDA9C7F00FD5D92800A6EA6E /* ctags.test */, + ); + path = test; + sourceTree = ""; + }; + FDA9C7FE0FD5D92800A6EA6E /* indent */ = { + isa = PBXGroup; + children = ( + FDA9C7FF0FD5D92800A6EA6E /* args.c */, + FDA9C8010FD5D92800A6EA6E /* indent.c */, + FDA9C8040FD5D92800A6EA6E /* io.c */, + FDA9C8050FD5D92800A6EA6E /* lexi.c */, + FDA9C8070FD5D92800A6EA6E /* parse.c */, + FDA9C8080FD5D92800A6EA6E /* pr_comment.c */, + FDA9C8020FD5D92800A6EA6E /* indent_codes.h */, + FDA9C8030FD5D92800A6EA6E /* indent_globs.h */, + FDA9C8000FD5D92800A6EA6E /* indent.1 */, + FDA9C8090FD5D92800A6EA6E /* README */, + ); + path = indent; + sourceTree = ""; + }; + FDA9C80A0FD5D92800A6EA6E /* lorder */ = { + isa = PBXGroup; + children = ( + FDA9C80C0FD5D92800A6EA6E /* lorder.sh */, + FDA9C80B0FD5D92800A6EA6E /* lorder.1 */, + ); + path = lorder; + sourceTree = ""; + }; + FDA9C8160FD5D92800A6EA6E /* rpcgen */ = { + isa = PBXGroup; + children = ( + FDA9C8180FD5D92800A6EA6E /* rpc_clntout.c */, + FDA9C8190FD5D92800A6EA6E /* rpc_cout.c */, + FDA9C81A0FD5D92800A6EA6E /* rpc_hout.c */, + FDA9C81B0FD5D92800A6EA6E /* rpc_main.c */, + FDA9C81C0FD5D92800A6EA6E /* rpc_parse.c */, + FDA9C81E0FD5D92800A6EA6E /* rpc_sample.c */, + FDA9C81F0FD5D92800A6EA6E /* rpc_scan.c */, + FDA9C8210FD5D92800A6EA6E /* rpc_svcout.c */, + FDA9C8220FD5D92800A6EA6E /* rpc_tblout.c */, + FDA9C8230FD5D92800A6EA6E /* rpc_util.c */, + FDA9C81D0FD5D92800A6EA6E /* rpc_parse.h */, + FDA9C8200FD5D92800A6EA6E /* rpc_scan.h */, + FDA9C8240FD5D92800A6EA6E /* rpc_util.h */, + FDA9C8250FD5D92800A6EA6E /* rpcgen.1 */, + ); + path = rpcgen; + sourceTree = ""; + }; + FDA9C8260FD5D92800A6EA6E /* unifdef */ = { + isa = PBXGroup; + children = ( + FDA9C8290FD5D92800A6EA6E /* unifdef.c */, + FDA9C8280FD5D92800A6EA6E /* unifdef.1 */, + FDA9C82A0FD5D92800A6EA6E /* unifdefall.sh */, + ); + path = unifdef; + sourceTree = ""; + }; + FDA9C83B0FD5E7DB00A6EA6E /* Products */ = { + isa = PBXGroup; + children = ( + FDA9C83A0FD5E7DB00A6EA6E /* asa */, + FDA9C8550FD5E85900A6EA6E /* ctags */, + FDA9C8B20FD5EAA100A6EA6E /* indent */, + FDA9C8D60FD5EBA400A6EA6E /* rpcgen */, + FDA9C8F80FD5EC2A00A6EA6E /* unifdef */, + ); + name = Products; + sourceTree = ""; + }; + FDA9C9280FD5ED6700A6EA6E /* Source */ = { + isa = PBXGroup; + children = ( + FDA9C7E20FD5D90F00A6EA6E /* asa */, + FDA9C7E60FD5D92800A6EA6E /* ctags */, + FDA9C7FE0FD5D92800A6EA6E /* indent */, + FDA9C80A0FD5D92800A6EA6E /* lorder */, + FDA9C8160FD5D92800A6EA6E /* rpcgen */, + FDA9C8260FD5D92800A6EA6E /* unifdef */, + ); + name = Source; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + FDA9C8390FD5E7DB00A6EA6E /* asa */ = { + isa = PBXNativeTarget; + buildConfigurationList = FDA9C83E0FD5E7DC00A6EA6E /* Build configuration list for PBXNativeTarget "asa" */; + buildPhases = ( + FDA9C8370FD5E7DB00A6EA6E /* Sources */, + FDA9C8380FD5E7DB00A6EA6E /* Frameworks */, + FDA9C84F0FD5E82D00A6EA6E /* Install man1 */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = asa; + productName = asa; + productReference = FDA9C83A0FD5E7DB00A6EA6E /* asa */; + productType = "com.apple.product-type.tool"; + }; + FDA9C8540FD5E85900A6EA6E /* ctags */ = { + isa = PBXNativeTarget; + buildConfigurationList = FDA9C85D0FD5E86100A6EA6E /* Build configuration list for PBXNativeTarget "ctags" */; + buildPhases = ( + FDA9C8520FD5E85900A6EA6E /* Sources */, + FDA9C8530FD5E85900A6EA6E /* Frameworks */, + FDA9C8730FD5E89700A6EA6E /* Install man1 */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = ctags; + productName = ctags; + productReference = FDA9C8550FD5E85900A6EA6E /* ctags */; + productType = "com.apple.product-type.tool"; + }; + FDA9C8B10FD5EAA100A6EA6E /* indent */ = { + isa = PBXNativeTarget; + buildConfigurationList = FDA9C8B90FD5EAAD00A6EA6E /* Build configuration list for PBXNativeTarget "indent" */; + buildPhases = ( + FDA9C8AF0FD5EAA100A6EA6E /* Sources */, + FDA9C8B00FD5EAA100A6EA6E /* Frameworks */, + FDA9C8CA0FD5EAFC00A6EA6E /* Install man1 */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = indent; + productName = indent; + productReference = FDA9C8B20FD5EAA100A6EA6E /* indent */; + productType = "com.apple.product-type.tool"; + }; + FDA9C8D50FD5EBA400A6EA6E /* rpcgen */ = { + isa = PBXNativeTarget; + buildConfigurationList = FDA9C8DE0FD5EBB300A6EA6E /* Build configuration list for PBXNativeTarget "rpcgen" */; + buildPhases = ( + FDA9C8D30FD5EBA400A6EA6E /* Sources */, + FDA9C8D40FD5EBA400A6EA6E /* Frameworks */, + FDA9C8F40FD5EC0F00A6EA6E /* Install man1 */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = rpcgen; + productName = rpcgen; + productReference = FDA9C8D60FD5EBA400A6EA6E /* rpcgen */; + productType = "com.apple.product-type.tool"; + }; + FDA9C8F70FD5EC2A00A6EA6E /* unifdef */ = { + isa = PBXNativeTarget; + buildConfigurationList = FDA9C9000FD5EC3B00A6EA6E /* Build configuration list for PBXNativeTarget "unifdef" */; + buildPhases = ( + FDA9C8F50FD5EC2A00A6EA6E /* Sources */, + FDA9C8F60FD5EC2A00A6EA6E /* Frameworks */, + FDA9C9040FD5EC6800A6EA6E /* Install man1 */, + FDA9C9080FD5EC7500A6EA6E /* Install unifdefall */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = unifdef; + productName = unifdef; + productReference = FDA9C8F80FD5EC2A00A6EA6E /* unifdef */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + FDA9C7D70FD5D84000A6EA6E /* Project object */ = { + isa = PBXProject; + attributes = { + }; + buildConfigurationList = FDA9C7DA0FD5D84000A6EA6E /* Build configuration list for PBXProject "developer_cmds" */; + compatibilityVersion = "Xcode 2.4"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = FDA9C7D50FD5D84000A6EA6E; + productRefGroup = FDA9C83B0FD5E7DB00A6EA6E /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + FDA9C8500FD5E85100A6EA6E /* default */, + FDA9C8390FD5E7DB00A6EA6E /* asa */, + FDA9C8540FD5E85900A6EA6E /* ctags */, + FDA9C8B10FD5EAA100A6EA6E /* indent */, + FDA9C97F0FD5F05400A6EA6E /* lorder */, + FDA9C8D50FD5EBA400A6EA6E /* rpcgen */, + FDA9C8F70FD5EC2A00A6EA6E /* unifdef */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXShellScriptBuildPhase section */ + FDA9C9080FD5EC7500A6EA6E /* Install unifdefall */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 8; + files = ( + ); + inputPaths = ( + ); + name = "Install unifdefall"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 1; + shellPath = /bin/sh; + shellScript = ". \"$PROJECT_DIR\"/xcodescripts/install-unifdefall.sh"; + showEnvVarsInLog = 0; + }; + FDA9C97E0FD5F05400A6EA6E /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 8; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 1; + shellPath = /bin/sh; + shellScript = ". \"$PROJECT_DIR\"/xcodescripts/install-lorder.sh"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + FDA9C8370FD5E7DB00A6EA6E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + FDA9C83F0FD5E7E300A6EA6E /* asa.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDA9C8520FD5E85900A6EA6E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + FDA9C85F0FD5E87200A6EA6E /* C.c in Sources */, + FDA9C8600FD5E87200A6EA6E /* ctags.c in Sources */, + FDA9C8610FD5E87200A6EA6E /* fortran.c in Sources */, + FDA9C8620FD5E87200A6EA6E /* lisp.c in Sources */, + FDA9C8630FD5E87200A6EA6E /* print.c in Sources */, + FDA9C8640FD5E87200A6EA6E /* tree.c in Sources */, + FDA9C8650FD5E87200A6EA6E /* yacc.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDA9C8AF0FD5EAA100A6EA6E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + FDA9C8BA0FD5EAD700A6EA6E /* args.c in Sources */, + FDA9C8BB0FD5EAD700A6EA6E /* indent.c in Sources */, + FDA9C8BC0FD5EAD700A6EA6E /* io.c in Sources */, + FDA9C8BD0FD5EAD700A6EA6E /* lexi.c in Sources */, + FDA9C8BE0FD5EAD700A6EA6E /* parse.c in Sources */, + FDA9C8BF0FD5EAD700A6EA6E /* pr_comment.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDA9C8D30FD5EBA400A6EA6E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + FDA9C8DF0FD5EBE600A6EA6E /* rpc_clntout.c in Sources */, + FDA9C8E00FD5EBE600A6EA6E /* rpc_cout.c in Sources */, + FDA9C8E10FD5EBE600A6EA6E /* rpc_hout.c in Sources */, + FDA9C8E20FD5EBE600A6EA6E /* rpc_main.c in Sources */, + FDA9C8E30FD5EBE600A6EA6E /* rpc_parse.c in Sources */, + FDA9C8E40FD5EBE600A6EA6E /* rpc_sample.c in Sources */, + FDA9C8E50FD5EBE600A6EA6E /* rpc_scan.c in Sources */, + FDA9C8E60FD5EBE600A6EA6E /* rpc_svcout.c in Sources */, + FDA9C8E70FD5EBE600A6EA6E /* rpc_tblout.c in Sources */, + FDA9C8E80FD5EBE600A6EA6E /* rpc_util.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDA9C8F50FD5EC2A00A6EA6E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + FDA9C9010FD5EC4800A6EA6E /* unifdef.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + FDA9C8590FD5E85C00A6EA6E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = FDA9C8390FD5E7DB00A6EA6E /* asa */; + targetProxy = FDA9C8580FD5E85C00A6EA6E /* PBXContainerItemProxy */; + }; + FDA9C85B0FD5E85E00A6EA6E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = FDA9C8540FD5E85900A6EA6E /* ctags */; + targetProxy = FDA9C85A0FD5E85E00A6EA6E /* PBXContainerItemProxy */; + }; + FDA9C8B60FD5EAA500A6EA6E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = FDA9C8B10FD5EAA100A6EA6E /* indent */; + targetProxy = FDA9C8B50FD5EAA500A6EA6E /* PBXContainerItemProxy */; + }; + FDA9C8DA0FD5EBB200A6EA6E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = FDA9C8D50FD5EBA400A6EA6E /* rpcgen */; + targetProxy = FDA9C8D90FD5EBB200A6EA6E /* PBXContainerItemProxy */; + }; + FDA9C8FC0FD5EC3300A6EA6E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = FDA9C8F70FD5EC2A00A6EA6E /* unifdef */; + targetProxy = FDA9C8FB0FD5EC3300A6EA6E /* PBXContainerItemProxy */; + }; + FDA9C9870FD5F06900A6EA6E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = FDA9C97F0FD5F05400A6EA6E /* lorder */; + targetProxy = FDA9C9860FD5F06900A6EA6E /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + FDA9C7D90FD5D84000A6EA6E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = YES; + CURRENT_PROJECT_VERSION = "$(RC_ProjectSourceVersion)"; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + INSTALL_MODE_FLAG = "ugo-w,a+rX"; + PREBINDING = NO; + USE_HEADERMAP = NO; + VERSIONING_SYSTEM = "apple-generic"; + ZERO_LINK = NO; + }; + name = Release; + }; + FDA9C83D0FD5E7DB00A6EA6E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + INSTALL_PATH = "$(DT_TOOLCHAIN_DIR)/usr/bin"; + PRODUCT_NAME = asa; + }; + name = Release; + }; + FDA9C8510FD5E85100A6EA6E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = default; + }; + name = Release; + }; + FDA9C8570FD5E85900A6EA6E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + INSTALL_PATH = "$(DT_TOOLCHAIN_DIR)/usr/bin"; + PRODUCT_NAME = ctags; + }; + name = Release; + }; + FDA9C8B40FD5EAA200A6EA6E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + INSTALL_PATH = "$(DT_TOOLCHAIN_DIR)/usr/bin"; + PRODUCT_NAME = indent; + }; + name = Release; + }; + FDA9C8D80FD5EBA400A6EA6E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + INSTALL_PATH = "$(DT_TOOLCHAIN_DIR)/usr/bin"; + PRODUCT_NAME = rpcgen; + }; + name = Release; + }; + FDA9C8FA0FD5EC2A00A6EA6E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + INSTALL_PATH = "$(DT_TOOLCHAIN_DIR)/usr/bin"; + PRODUCT_NAME = unifdef; + }; + name = Release; + }; + FDA9C9800FD5F05400A6EA6E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = lorder; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + FDA9C7DA0FD5D84000A6EA6E /* Build configuration list for PBXProject "developer_cmds" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FDA9C7D90FD5D84000A6EA6E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + FDA9C83E0FD5E7DC00A6EA6E /* Build configuration list for PBXNativeTarget "asa" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FDA9C83D0FD5E7DB00A6EA6E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + FDA9C85D0FD5E86100A6EA6E /* Build configuration list for PBXNativeTarget "ctags" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FDA9C8570FD5E85900A6EA6E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + FDA9C85E0FD5E86100A6EA6E /* Build configuration list for PBXAggregateTarget "default" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FDA9C8510FD5E85100A6EA6E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + FDA9C8B90FD5EAAD00A6EA6E /* Build configuration list for PBXNativeTarget "indent" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FDA9C8B40FD5EAA200A6EA6E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + FDA9C8DE0FD5EBB300A6EA6E /* Build configuration list for PBXNativeTarget "rpcgen" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FDA9C8D80FD5EBA400A6EA6E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + FDA9C9000FD5EC3B00A6EA6E /* Build configuration list for PBXNativeTarget "unifdef" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FDA9C8FA0FD5EC2A00A6EA6E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + FDA9C98B0FD5F08700A6EA6E /* Build configuration list for PBXAggregateTarget "lorder" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FDA9C9800FD5F05400A6EA6E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = FDA9C7D70FD5D84000A6EA6E /* Project object */; +} diff --git a/developer_cmds/developer_cmds.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/developer_cmds/developer_cmds.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/developer_cmds/developer_cmds.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/developer_cmds/indent/args.c b/developer_cmds/indent/args.c new file mode 100644 index 0000000..507be03 --- /dev/null +++ b/developer_cmds/indent/args.c @@ -0,0 +1,327 @@ +/* + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if 0 +#ifndef lint +static char sccsid[] = "@(#)args.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ +#endif + +#include +__FBSDID("$FreeBSD: src/usr.bin/indent/args.c,v 1.16 2010/03/31 17:05:30 avg Exp $"); + +/* + * Argument scanning and profile reading code. Default parameters are set + * here as well. + */ + +#include +#include +#include +#include +#include +#include +#include "indent_globs.h" +#include "indent.h" + +/* profile types */ +#define PRO_SPECIAL 1 /* special case */ +#define PRO_BOOL 2 /* boolean */ +#define PRO_INT 3 /* integer */ +#define PRO_FONT 4 /* troff font */ + +/* profile specials for booleans */ +#define ON 1 /* turn it on */ +#define OFF 0 /* turn it off */ + +/* profile specials for specials */ +#define IGN 1 /* ignore it */ +#define CLI 2 /* case label indent (float) */ +#define STDIN 3 /* use stdin */ +#define KEY 4 /* type (keyword) */ + +static void scan_profile(FILE *); + +const char *option_source = "?"; + +/* + * N.B.: because of the way the table here is scanned, options whose names are + * substrings of other options must occur later; that is, with -lp vs -l, -lp + * must be first. Also, while (most) booleans occur more than once, the last + * default value is the one actually assigned. + */ +struct pro { + const char *p_name; /* name, e.g. -bl, -cli */ + int p_type; /* type (int, bool, special) */ + int p_default; /* the default value (if int) */ + int p_special; /* depends on type */ + int *p_obj; /* the associated variable */ +} pro[] = { + + {"T", PRO_SPECIAL, 0, KEY, 0}, + {"bacc", PRO_BOOL, false, ON, &blanklines_around_conditional_compilation}, + {"badp", PRO_BOOL, false, ON, &blanklines_after_declarations_at_proctop}, + {"bad", PRO_BOOL, false, ON, &blanklines_after_declarations}, + {"bap", PRO_BOOL, false, ON, &blanklines_after_procs}, + {"bbb", PRO_BOOL, false, ON, &blanklines_before_blockcomments}, + {"bc", PRO_BOOL, true, OFF, &ps.leave_comma}, + {"bl", PRO_BOOL, true, OFF, &btype_2}, + {"br", PRO_BOOL, true, ON, &btype_2}, + {"bs", PRO_BOOL, false, ON, &Bill_Shannon}, + {"cdb", PRO_BOOL, true, ON, &comment_delimiter_on_blankline}, + {"cd", PRO_INT, 0, 0, &ps.decl_com_ind}, + {"ce", PRO_BOOL, true, ON, &cuddle_else}, + {"ci", PRO_INT, 0, 0, &continuation_indent}, + {"cli", PRO_SPECIAL, 0, CLI, 0}, + {"c", PRO_INT, 33, 0, &ps.com_ind}, + {"di", PRO_INT, 16, 0, &ps.decl_indent}, + {"dj", PRO_BOOL, false, ON, &ps.ljust_decl}, + {"d", PRO_INT, 0, 0, &ps.unindent_displace}, + {"eei", PRO_BOOL, false, ON, &extra_expression_indent}, + {"ei", PRO_BOOL, true, ON, &ps.else_if}, + {"fbc", PRO_FONT, 0, 0, (int *) &blkcomf}, + {"fbs", PRO_BOOL, true, ON, &function_brace_split}, + {"fbx", PRO_FONT, 0, 0, (int *) &boxcomf}, + {"fb", PRO_FONT, 0, 0, (int *) &bodyf}, + {"fc1", PRO_BOOL, true, ON, &format_col1_comments}, + {"fcb", PRO_BOOL, true, ON, &format_block_comments}, + {"fc", PRO_FONT, 0, 0, (int *) &scomf}, + {"fk", PRO_FONT, 0, 0, (int *) &keywordf}, + {"fs", PRO_FONT, 0, 0, (int *) &stringf}, + {"ip", PRO_BOOL, true, ON, &ps.indent_parameters}, + {"i", PRO_INT, 8, 0, &ps.ind_size}, + {"lc", PRO_INT, 0, 0, &block_comment_max_col}, + {"ldi", PRO_INT, -1, 0, &ps.local_decl_indent}, + {"lp", PRO_BOOL, true, ON, &lineup_to_parens}, + {"l", PRO_INT, 78, 0, &max_col}, + {"nbacc", PRO_BOOL, false, OFF, &blanklines_around_conditional_compilation}, + {"nbadp", PRO_BOOL, false, OFF, &blanklines_after_declarations_at_proctop}, + {"nbad", PRO_BOOL, false, OFF, &blanklines_after_declarations}, + {"nbap", PRO_BOOL, false, OFF, &blanklines_after_procs}, + {"nbbb", PRO_BOOL, false, OFF, &blanklines_before_blockcomments}, + {"nbc", PRO_BOOL, true, ON, &ps.leave_comma}, + {"nbs", PRO_BOOL, false, OFF, &Bill_Shannon}, + {"ncdb", PRO_BOOL, true, OFF, &comment_delimiter_on_blankline}, + {"nce", PRO_BOOL, true, OFF, &cuddle_else}, + {"ndj", PRO_BOOL, false, OFF, &ps.ljust_decl}, + {"neei", PRO_BOOL, false, OFF, &extra_expression_indent}, + {"nei", PRO_BOOL, true, OFF, &ps.else_if}, + {"nfbs", PRO_BOOL, true, OFF, &function_brace_split}, + {"nfc1", PRO_BOOL, true, OFF, &format_col1_comments}, + {"nfcb", PRO_BOOL, true, OFF, &format_block_comments}, + {"nip", PRO_BOOL, true, OFF, &ps.indent_parameters}, + {"nlp", PRO_BOOL, true, OFF, &lineup_to_parens}, + {"npcs", PRO_BOOL, false, OFF, &proc_calls_space}, + {"npro", PRO_SPECIAL, 0, IGN, 0}, + {"npsl", PRO_BOOL, true, OFF, &procnames_start_line}, + {"nps", PRO_BOOL, false, OFF, &pointer_as_binop}, + {"nsc", PRO_BOOL, true, OFF, &star_comment_cont}, + {"nsob", PRO_BOOL, false, OFF, &swallow_optional_blanklines}, + {"nut", PRO_BOOL, true, OFF, &use_tabs}, + {"nv", PRO_BOOL, false, OFF, &verbose}, + {"pcs", PRO_BOOL, false, ON, &proc_calls_space}, + {"psl", PRO_BOOL, true, ON, &procnames_start_line}, + {"ps", PRO_BOOL, false, ON, &pointer_as_binop}, + {"sc", PRO_BOOL, true, ON, &star_comment_cont}, + {"sob", PRO_BOOL, false, ON, &swallow_optional_blanklines}, + {"st", PRO_SPECIAL, 0, STDIN, 0}, + {"ta", PRO_BOOL, false, ON, &auto_typedefs}, + {"troff", PRO_BOOL, false, ON, &troff}, + {"ut", PRO_BOOL, true, ON, &use_tabs}, + {"v", PRO_BOOL, false, ON, &verbose}, + /* whew! */ + {0, 0, 0, 0, 0} +}; + +/* + * set_profile reads $HOME/.indent.pro and ./.indent.pro and handles arguments + * given in these files. + */ +void +set_profile(void) +{ + FILE *f; + char fname[PATH_MAX]; + static char prof[] = ".indent.pro"; + + snprintf(fname, sizeof(fname), "%s/%s", getenv("HOME"), prof); + if ((f = fopen(option_source = fname, "r")) != NULL) { + scan_profile(f); + (void) fclose(f); + } + if ((f = fopen(option_source = prof, "r")) != NULL) { + scan_profile(f); + (void) fclose(f); + } + option_source = "Command line"; +} + +static void +scan_profile(FILE *f) +{ + int comment, i; + char *p; + char buf[BUFSIZ]; + + while (1) { + p = buf; + comment = 0; + while ((i = getc(f)) != EOF) { + if (i == '*' && !comment && p > buf && p[-1] == '/') { + comment = p - buf; + *p++ = i; + } else if (i == '/' && comment && p > buf && p[-1] == '*') { + p = buf + comment - 1; + comment = 0; + } else if (isspace(i)) { + if (p > buf && !comment) + break; + } else { + *p++ = i; + } + } + if (p != buf) { + *p++ = 0; + if (verbose) + printf("profile: %s\n", buf); + set_option(buf); + } + else if (i == EOF) + return; + } +} + +const char *param_start; + +static int +eqin(const char *s1, const char *s2) +{ + while (*s1) { + if (*s1++ != *s2++) + return (false); + } + param_start = s2; + return (true); +} + +/* + * Set the defaults. + */ +void +set_defaults(void) +{ + struct pro *p; + + /* + * Because ps.case_indent is a float, we can't initialize it from the + * table: + */ + ps.case_indent = 0.0; /* -cli0.0 */ + for (p = pro; p->p_name; p++) + if (p->p_type != PRO_SPECIAL && p->p_type != PRO_FONT) + *p->p_obj = p->p_default; +} + +void +set_option(char *arg) +{ + struct pro *p; + + arg++; /* ignore leading "-" */ + for (p = pro; p->p_name; p++) + if (*p->p_name == *arg && eqin(p->p_name, arg)) + goto found; + errx(1, "%s: unknown parameter \"%s\"", option_source, arg - 1); +found: + switch (p->p_type) { + + case PRO_SPECIAL: + switch (p->p_special) { + + case IGN: + break; + + case CLI: + if (*param_start == 0) + goto need_param; + ps.case_indent = atof(param_start); + break; + + case STDIN: + if (input == 0) + input = stdin; + if (output == 0) + output = stdout; + break; + + case KEY: + if (*param_start == 0) + goto need_param; + { + char *str = strdup(param_start); + if (str == NULL) + err(1, NULL); + addkey(str, 4); + } + break; + + default: + errx(1, "set_option: internal error: p_special %d", p->p_special); + } + break; + + case PRO_BOOL: + if (p->p_special == OFF) + *p->p_obj = false; + else + *p->p_obj = true; + break; + + case PRO_INT: + if (!isdigit(*param_start)) { + need_param: + errx(1, "%s: ``%s'' requires a parameter", option_source, arg - 1); + } + *p->p_obj = atoi(param_start); + break; + + case PRO_FONT: + parsefont((struct fstate *) p->p_obj, param_start); + break; + + default: + errx(1, "set_option: internal error: p_type %d", p->p_type); + } +} diff --git a/developer_cmds/indent/indent.1 b/developer_cmds/indent/indent.1 new file mode 100644 index 0000000..f35ea95 --- /dev/null +++ b/developer_cmds/indent/indent.1 @@ -0,0 +1,559 @@ +.\" Copyright (c) 1980, 1990, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" Copyright (c) 1976 Board of Trustees of the University of Illinois. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)indent.1 8.1 (Berkeley) 7/1/93 +.\" $FreeBSD: src/usr.bin/indent/indent.1,v 1.28 2010/03/31 17:05:30 avg Exp $ +.\" +.Dd June 29, 2004 +.Dt INDENT 1 +.Os +.Sh NAME +.Nm indent +.Nd indent and format C program source +.Sh SYNOPSIS +.Nm +.Op Ar input_file Op Ar output_file +.Op Fl bacc | Fl nbacc +.Op Fl bad | Fl nbad +.Op Fl bap | Fl nbap +.Bk -words +.Op Fl bbb | Fl nbbb +.Ek +.Op Fl \&bc | Fl nbc +.Op Fl \&bl +.Op Fl \&br +.Op Fl c Ns Ar n +.Op Fl \&cd Ns Ar n +.Bk -words +.Op Fl cdb | Fl ncdb +.Ek +.Op Fl \&ce | Fl nce +.Op Fl \&ci Ns Ar n +.Op Fl cli Ns Ar n +.Op Fl d Ns Ar n +.Op Fl \&di Ns Ar n +.Bk -words +.Op Fl ei | Fl ei +.Op Fl eei | Fl eei +.Op Fl fbs | Fl nfbs +.Op Fl fc1 | Fl nfc1 +.Op Fl fcb | Fl nfcb +.Ek +.Op Fl i Ns Ar n +.Op Fl \&ip | Fl nip +.Op Fl l Ns Ar n +.Op Fl \&lc Ns Ar n +.Op Fl \&ldi Ns Ar n +.Op Fl \&lp | Fl nlp +.Op Fl npro +.Op Fl pcs | Fl npcs +.Op Fl psl | Fl npsl +.Op Fl \&sc | Fl nsc +.Bk -words +.Op Fl sob | Fl nsob +.Ek +.Op Fl \&st +.Op Fl \&ta +.Op Fl troff +.Op Fl ut | Fl nut +.Op Fl v | Fl \&nv +.Sh DESCRIPTION +.Nm +is a +.Em C +program formatter. +It reformats the +.Em C +program in the +.Ar input_file +according to the switches. +The switches which can be +specified are described below. +They may appear before or after the file +names. +.Pp +.Sy NOTE : +If you only specify an +.Ar input_file , +the formatting is +done `in-place', that is, the formatted file is written back into +.Ar input_file +and a backup copy of +.Ar input_file +is written in the current directory. +If +.Ar input_file +is named +.Sq Pa /blah/blah/file , +the backup file is named +.Sq Pa file.BAK . +.Pp +If +.Ar output_file +is specified, +.Nm +checks to make sure that it is different from +.Ar input_file . +.Pp +The options listed below control the formatting style imposed by +.Nm . +.Bl -tag -width Op +.It Fl bacc , nbacc +If +.Fl bacc +is specified, a blank line is forced around every conditional +compilation block. +For example, in front of every #ifdef and after every #endif. +Other blank lines surrounding such blocks will be swallowed. +The default is +.Fl nbacc . +.It Fl bad , nbad +If +.Fl bad +is specified, a blank line is forced after every block of +declarations. +The default is +.Fl nbad . +.It Fl bap , nbap +If +.Fl bap +is specified, a blank line is forced after every procedure body. +The default is +.Fl nbap . +.It Fl bbb , nbbb +If +.Fl bbb +is specified, a blank line is forced before every block comment. +The default is +.Fl nbbb . +.It Fl \&bc , nbc +If +.Fl \&bc +is specified, then a newline is forced after each comma in a declaration. +.Fl nbc +turns off this option. +The default is +.Fl \&nbc . +.It Fl \&br , \&bl +Specifying +.Fl \&bl +lines-up compound statements like this: +.Bd -literal -offset indent +if (...) +{ + code +} +.Ed +.Pp +Specifying +.Fl \&br +(the default) makes them look like this: +.Bd -literal -offset indent +if (...) { + code +} +.Ed +.Pp +.It Fl c Ns Ar n +The column in which comments on code start. +The default is 33. +.It Fl cd Ns Ar n +The column in which comments on declarations start. +The default +is for these comments to start in the same column as those on code. +.It Fl cdb , ncdb +Enables (disables) the placement of comment delimiters on blank lines. +With +this option enabled, comments look like this: +.Bd -literal -offset indent + /* + * this is a comment + */ +.Ed +.Pp +Rather than like this: +.Bd -literal -offset indent + /* this is a comment */ +.Ed +.Pp +This only affects block comments, not comments to the right of +code. +The default is +.Fl cdb . +.It Fl ce , nce +Enables (disables) forcing of `else's to cuddle up to the immediately preceding +`}'. +The default is +.Fl \&ce . +.It Fl \&ci Ns Ar n +Sets the continuation indent to be +.Ar n . +Continuation +lines will be indented that far from the beginning of the first line of the +statement. +Parenthesized expressions have extra indentation added to +indicate the nesting, unless +.Fl \&lp +is in effect +or the continuation indent is exactly half of the main indent. +.Fl \&ci +defaults to the same value as +.Fl i . +.It Fl cli Ns Ar n +Causes case labels to be indented +.Ar n +tab stops to the right of the containing +.Ic switch +statement. +.Fl cli0.5 +causes case labels to be indented half a tab stop. +The +default is +.Fl cli0 . +.It Fl d Ns Ar n +Controls the placement of comments which are not to the +right of code. +For example, +.Fl \&d\&1 +means that such comments are placed one indentation level to the +left of code. +Specifying the default +.Fl \&d\&0 +lines-up these comments with the code. +See the section on comment +indentation below. +.It Fl \&di Ns Ar n +Specifies the indentation, in character positions, +of global variable names and all struct/union member names +relative to the beginning of their type declaration. +The default is +.Fl di16 . +.It Fl dj , ndj +.Fl \&dj +left justifies declarations. +.Fl ndj +indents declarations the same as code. +The default is +.Fl ndj . +.It Fl \&ei , nei +Enables (disables) special +.Ic else-if +processing. +If it is enabled, an +.Ic if +following an +.Ic else +will have the same indentation as the preceding +.Ic \&if +statement. +The default is +.Fl ei . +.It Fl eei , neei +Enables (disables) extra indentation on continuation lines of +the expression part of +.Ic if +and +.Ic while +statements. +These continuation lines will be indented one extra level. +The default is +.Fl neei . +.It Fl fbs , nfbs +Enables (disables) splitting the function declaration and opening brace +across two lines. +The default is +.Fl fbs . +.It Fl fc1 , nfc1 +Enables (disables) the formatting of comments that start in column 1. +Often, comments whose leading `/' is in column 1 have been carefully +hand formatted by the programmer. +In such cases, +.Fl nfc1 +should be +used. +The default is +.Fl fc1 . +.It Fl fcb , nfcb +Enables (disables) the formatting of block comments (ones that begin +with `/*\\n'). +Often, block comments have been not so carefully hand formatted by the +programmer, but reformatting that would just change the line breaks is not +wanted. +In such cases, +.Fl nfcb +should be used. +Block comments are then handled like box comments. +The default is +.Fl fcb . +.It Fl i Ns Ar n +The number of spaces for one indentation level. +The default is 8. +.It Fl \&ip , nip +Enables (disables) the indentation of parameter declarations from the left +margin. +The default is +.Fl \&ip . +.It Fl l Ns Ar n +Maximum length of an output line. +The default is 78. +.It Fl \&ldi Ns Ar n +Specifies the indentation, in character positions, +of local variable names +relative to the beginning of their type declaration. +The default is for local variable names to be indented +by the same amount as global ones. +.It Fl \&lp , nlp +Lines-up code surrounded by parenthesis in continuation lines. +If a line +has a left paren which is not closed on that line, then continuation lines +will be lined up to start at the character position just after the left +paren. +For example, here is how a piece of continued code looks with +.Fl nlp +in effect: +.Bd -literal -offset indent +p1 = first_procedure(second_procedure(p2, p3), +\ \ third_procedure(p4, p5)); +.Ed +.Pp +With +.Fl lp +in effect (the default) the code looks somewhat clearer: +.Bd -literal -offset indent +p1\ =\ first_procedure(second_procedure(p2,\ p3), +\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ third_procedure(p4,\ p5)); +.Ed +.Pp +Inserting two more newlines we get: +.Bd -literal -offset indent +p1\ =\ first_procedure(second_procedure(p2, +\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ p3), +\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ third_procedure(p4, +\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ p5)); +.Ed +.It Fl npro +Causes the profile files, +.Sq Pa ./.indent.pro +and +.Sq Pa ~/.indent.pro , +to be ignored. +.It Fl pcs , npcs +If true +.Pq Fl pcs +all procedure calls will have a space inserted between +the name and the `('. +The default is +.Fl npcs . +.It Fl psl , npsl +If true +.Pq Fl psl +the names of procedures being defined are placed in +column 1 \- their types, if any, will be left on the previous lines. +The +default is +.Fl psl . +.It Fl \&sc , nsc +Enables (disables) the placement of asterisks (`*'s) at the left edge of all +comments. +The default is +.Fl sc . +.It Fl sob , nsob +If +.Fl sob +is specified, indent will swallow optional blank lines. +You can use this to +get rid of blank lines after declarations. +The default is +.Fl nsob . +.It Fl \&st +Causes +.Nm +to take its input from stdin and put its output to stdout. +.It Fl ta +Automatically add all identifiers ending in "_t" to the list +of type keywords. +.It Fl T Ns Ar typename +Adds +.Ar typename +to the list of type keywords. +Names accumulate: +.Fl T +can be specified more than once. +You need to specify all the typenames that +appear in your program that are defined by +.Ic typedef +\- nothing will be +harmed if you miss a few, but the program will not be formatted as nicely as +it should. +This sounds like a painful thing to have to do, but it is really +a symptom of a problem in C: +.Ic typedef +causes a syntactic change in the +language and +.Nm +cannot find all +instances of +.Ic typedef . +.It Fl troff +Causes +.Nm +to format the program for processing by +.Xr troff 1 . +.\" It will produce a fancy +.\" listing in much the same spirit as +.\" .Xr vgrind 1 . +If the output file is not specified, the default is standard output, +rather than formatting in place. +.It Fl ut , nut +Enables (disables) the use of tab characters in the output. +Tabs are assumed to be aligned on columns divisible by 8. +The default is +.Fl ut . +.It Fl v , \&nv +.Fl v +turns on `verbose' mode; +.Fl \&nv +turns it off. +When in verbose mode, +.Nm +reports when it splits one line of input into two or more lines of output, +and gives some size statistics at completion. +The default is +.Fl \&nv . +.El +.Pp +You may set up your own `profile' of defaults to +.Nm +by creating a file called +.Pa .indent.pro +in your login directory and/or the current directory and including +whatever switches you like. +A `.indent.pro' in the current directory takes +precedence over the one in your login directory. +If +.Nm +is run and a profile file exists, then it is read to set up the program's +defaults. +Switches on the command line, though, always override profile +switches. +The switches should be separated by spaces, tabs or newlines. +.Pp +.Ss Comments +.Sq Em Box +.Em comments . +.Nm +assumes that any comment with a dash or star immediately after the start of +comment (that is, `/*\-' or `/**') is a comment surrounded by a box of stars. +Each line of such a comment is left unchanged, except that its indentation +may be adjusted to account for the change in indentation of the first line +of the comment. +.Pp +.Em Straight text . +All other comments are treated as straight text. +.Nm +fits as many words (separated by blanks, tabs, or newlines) on a +line as possible. +Blank lines break paragraphs. +.Pp +.Ss Comment indentation +If a comment is on a line with code it is started in the `comment column', +which is set by the +.Fl c Ns Ns Ar n +command line parameter. +Otherwise, the comment is started at +.Ar n +indentation levels less than where code is currently being placed, where +.Ar n +is specified by the +.Fl d Ns Ns Ar n +command line parameter. +If the code on a line extends past the comment +column, the comment starts further to the right, and the right margin may be +automatically extended in extreme cases. +.Pp +.Ss Preprocessor lines +In general, +.Nm +leaves preprocessor lines alone. +The only +reformatting that it will do is to straighten up trailing comments. +It +leaves embedded comments alone. +Conditional compilation +.Pq Ic #ifdef...#endif +is recognized and +.Nm +attempts to correctly +compensate for the syntactic peculiarities introduced. +.Pp +.Ss C syntax +.Nm +understands a substantial amount about the syntax of C, but it +has a `forgiving' parser. +It attempts to cope with the usual sorts of +incomplete and misformed syntax. +In particular, the use of macros like: +.Pp +.Dl #define forever for(;;) +.Pp +is handled properly. +.Sh ENVIRONMENT +.Nm +uses the +.Ev HOME +environment variable. +.Sh FILES +.Bl -tag -width "./.indent.pro" -compact +.It Pa ./.indent.pro +profile file +.It Pa ~/.indent.pro +profile file +.El +.Sh HISTORY +The +.Nm +command appeared in +.Bx 4.2 . +.Sh BUGS +.Nm +has even more switches than +.Xr ls 1 . +.Pp +A common mistake that often causes grief is typing: +.Pp +.Dl indent *.c +.Pp +to the shell in an attempt to indent all the +.Tn C +programs in a directory. +This is probably a bug, not a feature. diff --git a/developer_cmds/indent/indent.c b/developer_cmds/indent/indent.c new file mode 100644 index 0000000..b88118e --- /dev/null +++ b/developer_cmds/indent/indent.c @@ -0,0 +1,1234 @@ +/* + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1976 Board of Trustees of the University of Illinois. + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static const char copyright[] = +"@(#) Copyright (c) 1985 Sun Microsystems, Inc.\n\ +@(#) Copyright (c) 1976 Board of Trustees of the University of Illinois.\n\ +@(#) Copyright (c) 1980, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#if 0 +#ifndef lint +static char sccsid[] = "@(#)indent.c 5.17 (Berkeley) 6/7/93"; +#endif /* not lint */ +#endif + +#include +__FBSDID("$FreeBSD: src/usr.bin/indent/indent.c,v 1.28 2011/12/30 11:02:40 uqs Exp $"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include "indent_globs.h" +#include "indent_codes.h" +#include "indent.h" + +static void bakcopy(void); + +const char *in_name = "Standard Input"; /* will always point to name of input + * file */ +const char *out_name = "Standard Output"; /* will always point to name + * of output file */ +char bakfile[MAXPATHLEN] = ""; + +int +main(int argc, char **argv) +{ + + int dec_ind; /* current indentation for declarations */ + int di_stack[20]; /* a stack of structure indentation levels */ + int flushed_nl; /* used when buffering up comments to remember + * that a newline was passed over */ + int force_nl; /* when true, code must be broken */ + int hd_type = 0; /* used to store type of stmt for if (...), + * for (...), etc */ + int i; /* local loop counter */ + int scase; /* set to true when we see a case, so we will + * know what to do with the following colon */ + int sp_sw; /* when true, we are in the expression of + * if(...), while(...), etc. */ + int squest; /* when this is positive, we have seen a ? + * without the matching : in a ?: + * construct */ + const char *t_ptr; /* used for copying tokens */ + int tabs_to_var; /* true if using tabs to indent to var name */ + int type_code; /* the type of token, returned by lexi */ + + int last_else = 0; /* true iff last keyword was an else */ + + + /*-----------------------------------------------*\ + | INITIALIZATION | + \*-----------------------------------------------*/ + + found_err = 0; + + ps.p_stack[0] = stmt; /* this is the parser's stack */ + ps.last_nl = true; /* this is true if the last thing scanned was + * a newline */ + ps.last_token = semicolon; + combuf = (char *) malloc(bufsize); + if (combuf == NULL) + err(1, NULL); + labbuf = (char *) malloc(bufsize); + if (labbuf == NULL) + err(1, NULL); + codebuf = (char *) malloc(bufsize); + if (codebuf == NULL) + err(1, NULL); + tokenbuf = (char *) malloc(bufsize); + if (tokenbuf == NULL) + err(1, NULL); + l_com = combuf + bufsize - 5; + l_lab = labbuf + bufsize - 5; + l_code = codebuf + bufsize - 5; + l_token = tokenbuf + bufsize - 5; + combuf[0] = codebuf[0] = labbuf[0] = ' '; /* set up code, label, and + * comment buffers */ + combuf[1] = codebuf[1] = labbuf[1] = '\0'; + ps.else_if = 1; /* Default else-if special processing to on */ + s_lab = e_lab = labbuf + 1; + s_code = e_code = codebuf + 1; + s_com = e_com = combuf + 1; + s_token = e_token = tokenbuf + 1; + + in_buffer = (char *) malloc(10); + if (in_buffer == NULL) + err(1, NULL); + in_buffer_limit = in_buffer + 8; + buf_ptr = buf_end = in_buffer; + line_no = 1; + had_eof = ps.in_decl = ps.decl_on_line = break_comma = false; + sp_sw = force_nl = false; + ps.in_or_st = false; + ps.bl_line = true; + dec_ind = 0; + di_stack[ps.dec_nest = 0] = 0; + ps.want_blank = ps.in_stmt = ps.ind_stmt = false; + + scase = ps.pcase = false; + squest = 0; + sc_end = 0; + bp_save = 0; + be_save = 0; + + output = 0; + tabs_to_var = 0; + + /*--------------------------------------------------*\ + | COMMAND LINE SCAN | + \*--------------------------------------------------*/ + +#ifdef undef + max_col = 78; /* -l78 */ + lineup_to_parens = 1; /* -lp */ + ps.ljust_decl = 0; /* -ndj */ + ps.com_ind = 33; /* -c33 */ + star_comment_cont = 1; /* -sc */ + ps.ind_size = 8; /* -i8 */ + verbose = 0; + ps.decl_indent = 16; /* -di16 */ + ps.local_decl_indent = -1; /* if this is not set to some nonnegative value + * by an arg, we will set this equal to + * ps.decl_ind */ + ps.indent_parameters = 1; /* -ip */ + ps.decl_com_ind = 0; /* if this is not set to some positive value + * by an arg, we will set this equal to + * ps.com_ind */ + btype_2 = 1; /* -br */ + cuddle_else = 1; /* -ce */ + ps.unindent_displace = 0; /* -d0 */ + ps.case_indent = 0; /* -cli0 */ + format_block_comments = 1; /* -fcb */ + format_col1_comments = 1; /* -fc1 */ + procnames_start_line = 1; /* -psl */ + proc_calls_space = 0; /* -npcs */ + comment_delimiter_on_blankline = 1; /* -cdb */ + ps.leave_comma = 1; /* -nbc */ +#endif + + for (i = 1; i < argc; ++i) + if (strcmp(argv[i], "-npro") == 0) + break; + set_defaults(); + if (i >= argc) + set_profile(); + + for (i = 1; i < argc; ++i) { + + /* + * look thru args (if any) for changes to defaults + */ + if (argv[i][0] != '-') {/* no flag on parameter */ + if (input == NULL) { /* we must have the input file */ + in_name = argv[i]; /* remember name of input file */ + input = fopen(in_name, "r"); + if (input == NULL) /* check for open error */ + err(1, "%s", in_name); + continue; + } + else if (output == NULL) { /* we have the output file */ + out_name = argv[i]; /* remember name of output file */ + if (strcmp(in_name, out_name) == 0) { /* attempt to overwrite + * the file */ + errx(1, "input and output files must be different"); + } + output = fopen(out_name, "w"); + if (output == NULL) /* check for create error */ + err(1, "%s", out_name); + continue; + } + errx(1, "unknown parameter: %s", argv[i]); + } + else + set_option(argv[i]); + } /* end of for */ + if (input == NULL) + input = stdin; + if (output == NULL) { + if (troff || input == stdin) + output = stdout; + else { + out_name = in_name; + bakcopy(); + } + } + if (ps.com_ind <= 1) + ps.com_ind = 2; /* dont put normal comments before column 2 */ + if (troff) { + if (bodyf.font[0] == 0) + parsefont(&bodyf, "R"); + if (scomf.font[0] == 0) + parsefont(&scomf, "I"); + if (blkcomf.font[0] == 0) + blkcomf = scomf, blkcomf.size += 2; + if (boxcomf.font[0] == 0) + boxcomf = blkcomf; + if (stringf.font[0] == 0) + parsefont(&stringf, "L"); + if (keywordf.font[0] == 0) + parsefont(&keywordf, "B"); + writefdef(&bodyf, 'B'); + writefdef(&scomf, 'C'); + writefdef(&blkcomf, 'L'); + writefdef(&boxcomf, 'X'); + writefdef(&stringf, 'S'); + writefdef(&keywordf, 'K'); + } + if (block_comment_max_col <= 0) + block_comment_max_col = max_col; + if (ps.local_decl_indent < 0) /* if not specified by user, set this */ + ps.local_decl_indent = ps.decl_indent; + if (ps.decl_com_ind <= 0) /* if not specified by user, set this */ + ps.decl_com_ind = ps.ljust_decl ? (ps.com_ind <= 10 ? 2 : ps.com_ind - 8) : ps.com_ind; + if (continuation_indent == 0) + continuation_indent = ps.ind_size; + fill_buffer(); /* get first batch of stuff into input buffer */ + + parse(semicolon); + { + char *p = buf_ptr; + int col = 1; + + while (1) { + if (*p == ' ') + col++; + else if (*p == '\t') + col = ((col - 1) & ~7) + 9; + else + break; + p++; + } + if (col > ps.ind_size) + ps.ind_level = ps.i_l_follow = col / ps.ind_size; + } + if (troff) { + const char *p = in_name, + *beg = in_name; + + while (*p) + if (*p++ == '/') + beg = p; + fprintf(output, ".Fn \"%s\"\n", beg); + } + /* + * START OF MAIN LOOP + */ + + while (1) { /* this is the main loop. it will go until we + * reach eof */ + int is_procname; + + type_code = lexi(); /* lexi reads one token. The actual + * characters read are stored in "token". lexi + * returns a code indicating the type of token */ + is_procname = ps.procname[0]; + + /* + * The following code moves everything following an if (), while (), + * else, etc. up to the start of the following stmt to a buffer. This + * allows proper handling of both kinds of brace placement. + */ + + flushed_nl = false; + while (ps.search_brace) { /* if we scanned an if(), while(), + * etc., we might need to copy stuff + * into a buffer we must loop, copying + * stuff into save_com, until we find + * the start of the stmt which follows + * the if, or whatever */ + switch (type_code) { + case newline: + ++line_no; + flushed_nl = true; + case form_feed: + break; /* form feeds and newlines found here will be + * ignored */ + + case lbrace: /* this is a brace that starts the compound + * stmt */ + if (sc_end == 0) { /* ignore buffering if a comment wasn't + * stored up */ + ps.search_brace = false; + goto check_type; + } + if (btype_2) { + save_com[0] = '{'; /* we either want to put the brace + * right after the if */ + goto sw_buffer; /* go to common code to get out of + * this loop */ + } + case comment: /* we have a comment, so we must copy it into + * the buffer */ + if (!flushed_nl || sc_end != 0) { + if (sc_end == 0) { /* if this is the first comment, we + * must set up the buffer */ + save_com[0] = save_com[1] = ' '; + sc_end = &(save_com[2]); + } + else { + *sc_end++ = '\n'; /* add newline between + * comments */ + *sc_end++ = ' '; + --line_no; + } + *sc_end++ = '/'; /* copy in start of comment */ + *sc_end++ = '*'; + + for (;;) { /* loop until we get to the end of the comment */ + *sc_end = *buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + + if (*sc_end++ == '*' && *buf_ptr == '/') + break; /* we are at end of comment */ + + if (sc_end >= &(save_com[sc_size])) { /* check for temp buffer + * overflow */ + diag2(1, "Internal buffer overflow - Move big comment from right after if, while, or whatever"); + fflush(output); + exit(1); + } + } + *sc_end++ = '/'; /* add ending slash */ + if (++buf_ptr >= buf_end) /* get past / in buffer */ + fill_buffer(); + break; + } + default: /* it is the start of a normal statement */ + if (flushed_nl) /* if we flushed a newline, make sure it is + * put back */ + force_nl = true; + if ((type_code == sp_paren && *token == 'i' + && last_else && ps.else_if) + || (type_code == sp_nparen && *token == 'e' + && e_code != s_code && e_code[-1] == '}')) + force_nl = false; + + if (sc_end == 0) { /* ignore buffering if comment wasn't + * saved up */ + ps.search_brace = false; + goto check_type; + } + if (force_nl) { /* if we should insert a nl here, put it into + * the buffer */ + force_nl = false; + --line_no; /* this will be re-increased when the nl is + * read from the buffer */ + *sc_end++ = '\n'; + *sc_end++ = ' '; + if (verbose && !flushed_nl) /* print error msg if the line + * was not already broken */ + diag2(0, "Line broken"); + flushed_nl = false; + } + for (t_ptr = token; *t_ptr; ++t_ptr) + *sc_end++ = *t_ptr; /* copy token into temp buffer */ + ps.procname[0] = 0; + + sw_buffer: + ps.search_brace = false; /* stop looking for start of + * stmt */ + bp_save = buf_ptr; /* save current input buffer */ + be_save = buf_end; + buf_ptr = save_com; /* fix so that subsequent calls to + * lexi will take tokens out of + * save_com */ + *sc_end++ = ' ';/* add trailing blank, just in case */ + buf_end = sc_end; + sc_end = 0; + break; + } /* end of switch */ + if (type_code != 0) /* we must make this check, just in case there + * was an unexpected EOF */ + type_code = lexi(); /* read another token */ + /* if (ps.search_brace) ps.procname[0] = 0; */ + if ((is_procname = ps.procname[0]) && flushed_nl + && !procnames_start_line && ps.in_decl + && type_code == ident) + flushed_nl = 0; + } /* end of while (search_brace) */ + last_else = 0; +check_type: + if (type_code == 0) { /* we got eof */ + if (s_lab != e_lab || s_code != e_code + || s_com != e_com) /* must dump end of line */ + dump_line(); + if (ps.tos > 1) /* check for balanced braces */ + diag2(1, "Stuff missing from end of file"); + + if (verbose) { + printf("There were %d output lines and %d comments\n", + ps.out_lines, ps.out_coms); + printf("(Lines with comments)/(Lines with code): %6.3f\n", + (1.0 * ps.com_lines) / code_lines); + } + fflush(output); + exit(found_err); + } + if ( + (type_code != comment) && + (type_code != newline) && + (type_code != preesc) && + (type_code != form_feed)) { + if (force_nl && + (type_code != semicolon) && + (type_code != lbrace || !btype_2)) { + /* we should force a broken line here */ + if (verbose && !flushed_nl) + diag2(0, "Line broken"); + flushed_nl = false; + dump_line(); + ps.want_blank = false; /* dont insert blank at line start */ + force_nl = false; + } + ps.in_stmt = true; /* turn on flag which causes an extra level of + * indentation. this is turned off by a ; or + * '}' */ + if (s_com != e_com) { /* the turkey has embedded a comment + * in a line. fix it */ + *e_code++ = ' '; + for (t_ptr = s_com; *t_ptr; ++t_ptr) { + CHECK_SIZE_CODE; + *e_code++ = *t_ptr; + } + *e_code++ = ' '; + *e_code = '\0'; /* null terminate code sect */ + ps.want_blank = false; + e_com = s_com; + } + } + else if (type_code != comment) /* preserve force_nl thru a comment */ + force_nl = false; /* cancel forced newline after newline, form + * feed, etc */ + + + + /*-----------------------------------------------------*\ + | do switch on type of token scanned | + \*-----------------------------------------------------*/ + CHECK_SIZE_CODE; + switch (type_code) { /* now, decide what to do with the token */ + + case form_feed: /* found a form feed in line */ + ps.use_ff = true; /* a form feed is treated much like a newline */ + dump_line(); + ps.want_blank = false; + break; + + case newline: + if (ps.last_token != comma || ps.p_l_follow > 0 + || !ps.leave_comma || ps.block_init || !break_comma || s_com != e_com) { + dump_line(); + ps.want_blank = false; + } + ++line_no; /* keep track of input line number */ + break; + + case lparen: /* got a '(' or '[' */ + ++ps.p_l_follow; /* count parens to make Healy happy */ + if (ps.want_blank && *token != '[' && + (ps.last_token != ident || proc_calls_space + || (ps.its_a_keyword && (!ps.sizeof_keyword || Bill_Shannon)))) + *e_code++ = ' '; + if (ps.in_decl && !ps.block_init) + if (troff && !ps.dumped_decl_indent && !is_procname && ps.last_token == decl) { + ps.dumped_decl_indent = 1; + sprintf(e_code, "\n.Du %dp+\200p \"%s\"\n", dec_ind * 7, token); + e_code += strlen(e_code); + } + else { + while ((e_code - s_code) < dec_ind) { + CHECK_SIZE_CODE; + *e_code++ = ' '; + } + *e_code++ = token[0]; + } + else + *e_code++ = token[0]; + ps.paren_indents[ps.p_l_follow - 1] = e_code - s_code; + if (sp_sw && ps.p_l_follow == 1 && extra_expression_indent + && ps.paren_indents[0] < 2 * ps.ind_size) + ps.paren_indents[0] = 2 * ps.ind_size; + ps.want_blank = false; + if (ps.in_or_st && *token == '(' && ps.tos <= 2) { + /* + * this is a kluge to make sure that declarations will be + * aligned right if proc decl has an explicit type on it, i.e. + * "int a(x) {..." + */ + parse(semicolon); /* I said this was a kluge... */ + ps.in_or_st = false; /* turn off flag for structure decl or + * initialization */ + } + if (ps.sizeof_keyword) + ps.sizeof_mask |= 1 << ps.p_l_follow; + break; + + case rparen: /* got a ')' or ']' */ + rparen_count--; + if (ps.cast_mask & (1 << ps.p_l_follow) & ~ps.sizeof_mask) { + ps.last_u_d = true; + ps.cast_mask &= (1 << ps.p_l_follow) - 1; + ps.want_blank = false; + } else + ps.want_blank = true; + ps.sizeof_mask &= (1 << ps.p_l_follow) - 1; + if (--ps.p_l_follow < 0) { + ps.p_l_follow = 0; + diag3(0, "Extra %c", *token); + } + if (e_code == s_code) /* if the paren starts the line */ + ps.paren_level = ps.p_l_follow; /* then indent it */ + + *e_code++ = token[0]; + + if (sp_sw && (ps.p_l_follow == 0)) { /* check for end of if + * (...), or some such */ + sp_sw = false; + force_nl = true;/* must force newline after if */ + ps.last_u_d = true; /* inform lexi that a following + * operator is unary */ + ps.in_stmt = false; /* dont use stmt continuation + * indentation */ + + parse(hd_type); /* let parser worry about if, or whatever */ + } + ps.search_brace = btype_2; /* this should insure that constructs + * such as main(){...} and int[]{...} + * have their braces put in the right + * place */ + break; + + case unary_op: /* this could be any unary operation */ + if (ps.want_blank) + *e_code++ = ' '; + + if (troff && !ps.dumped_decl_indent && ps.in_decl && !is_procname) { + sprintf(e_code, "\n.Du %dp+\200p \"%s\"\n", dec_ind * 7, token); + ps.dumped_decl_indent = 1; + e_code += strlen(e_code); + } + else { + const char *res = token; + + if (ps.in_decl && !ps.block_init) { /* if this is a unary op + * in a declaration, we + * should indent this + * token */ + for (i = 0; token[i]; ++i); /* find length of token */ + while ((e_code - s_code) < (dec_ind - i)) { + CHECK_SIZE_CODE; + *e_code++ = ' '; /* pad it */ + } + } + if (troff && token[0] == '-' && token[1] == '>') + res = "\\(->"; + for (t_ptr = res; *t_ptr; ++t_ptr) { + CHECK_SIZE_CODE; + *e_code++ = *t_ptr; + } + } + ps.want_blank = false; + break; + + case binary_op: /* any binary operation */ + if (ps.want_blank) + *e_code++ = ' '; + { + const char *res = token; + + if (troff) + switch (token[0]) { + case '<': + if (token[1] == '=') + res = "\\(<="; + break; + case '>': + if (token[1] == '=') + res = "\\(>="; + break; + case '!': + if (token[1] == '=') + res = "\\(!="; + break; + case '|': + if (token[1] == '|') + res = "\\(br\\(br"; + else if (token[1] == 0) + res = "\\(br"; + break; + } + for (t_ptr = res; *t_ptr; ++t_ptr) { + CHECK_SIZE_CODE; + *e_code++ = *t_ptr; /* move the operator */ + } + } + ps.want_blank = true; + break; + + case postop: /* got a trailing ++ or -- */ + *e_code++ = token[0]; + *e_code++ = token[1]; + ps.want_blank = true; + break; + + case question: /* got a ? */ + squest++; /* this will be used when a later colon + * appears so we can distinguish the + * ?: construct */ + if (ps.want_blank) + *e_code++ = ' '; + *e_code++ = '?'; + ps.want_blank = true; + break; + + case casestmt: /* got word 'case' or 'default' */ + scase = true; /* so we can process the later colon properly */ + goto copy_id; + + case colon: /* got a ':' */ + if (squest > 0) { /* it is part of the ?: construct */ + --squest; + if (ps.want_blank) + *e_code++ = ' '; + *e_code++ = ':'; + ps.want_blank = true; + break; + } + if (ps.in_or_st) { + *e_code++ = ':'; + ps.want_blank = false; + break; + } + ps.in_stmt = false; /* seeing a label does not imply we are in a + * stmt */ + for (t_ptr = s_code; *t_ptr; ++t_ptr) + *e_lab++ = *t_ptr; /* turn everything so far into a label */ + e_code = s_code; + *e_lab++ = ':'; + *e_lab++ = ' '; + *e_lab = '\0'; + + force_nl = ps.pcase = scase; /* ps.pcase will be used by + * dump_line to decide how to + * indent the label. force_nl + * will force a case n: to be + * on a line by itself */ + scase = false; + ps.want_blank = false; + break; + + case semicolon: /* got a ';' */ + ps.in_or_st = false;/* we are not in an initialization or + * structure declaration */ + scase = false; /* these will only need resetting in an error */ + squest = 0; + if (ps.last_token == rparen && rparen_count == 0) + ps.in_parameter_declaration = 0; + ps.cast_mask = 0; + ps.sizeof_mask = 0; + ps.block_init = 0; + ps.block_init_level = 0; + ps.just_saw_decl--; + + if (ps.in_decl && s_code == e_code && !ps.block_init) + while ((e_code - s_code) < (dec_ind - 1)) { + CHECK_SIZE_CODE; + *e_code++ = ' '; + } + + ps.in_decl = (ps.dec_nest > 0); /* if we were in a first level + * structure declaration, we + * arent any more */ + + if ((!sp_sw || hd_type != forstmt) && ps.p_l_follow > 0) { + + /* + * This should be true iff there were unbalanced parens in the + * stmt. It is a bit complicated, because the semicolon might + * be in a for stmt + */ + diag2(1, "Unbalanced parens"); + ps.p_l_follow = 0; + if (sp_sw) { /* this is a check for an if, while, etc. with + * unbalanced parens */ + sp_sw = false; + parse(hd_type); /* dont lose the if, or whatever */ + } + } + *e_code++ = ';'; + ps.want_blank = true; + ps.in_stmt = (ps.p_l_follow > 0); /* we are no longer in the + * middle of a stmt */ + + if (!sp_sw) { /* if not if for (;;) */ + parse(semicolon); /* let parser know about end of stmt */ + force_nl = true;/* force newline after an end of stmt */ + } + break; + + case lbrace: /* got a '{' */ + ps.in_stmt = false; /* dont indent the {} */ + if (!ps.block_init) + force_nl = true;/* force other stuff on same line as '{' onto + * new line */ + else if (ps.block_init_level <= 0) + ps.block_init_level = 1; + else + ps.block_init_level++; + + if (s_code != e_code && !ps.block_init) { + if (!btype_2) { + dump_line(); + ps.want_blank = false; + } + else if (ps.in_parameter_declaration && !ps.in_or_st) { + ps.i_l_follow = 0; + if (function_brace_split) { /* dump the line prior to the + * brace ... */ + dump_line(); + ps.want_blank = false; + } else /* add a space between the decl and brace */ + ps.want_blank = true; + } + } + if (ps.in_parameter_declaration) + prefix_blankline_requested = 0; + + if (ps.p_l_follow > 0) { /* check for preceding unbalanced + * parens */ + diag2(1, "Unbalanced parens"); + ps.p_l_follow = 0; + if (sp_sw) { /* check for unclosed if, for, etc. */ + sp_sw = false; + parse(hd_type); + ps.ind_level = ps.i_l_follow; + } + } + if (s_code == e_code) + ps.ind_stmt = false; /* dont put extra indentation on line + * with '{' */ + if (ps.in_decl && ps.in_or_st) { /* this is either a structure + * declaration or an init */ + di_stack[ps.dec_nest++] = dec_ind; + /* ? dec_ind = 0; */ + } + else { + ps.decl_on_line = false; /* we can't be in the middle of + * a declaration, so don't do + * special indentation of + * comments */ + if (blanklines_after_declarations_at_proctop + && ps.in_parameter_declaration) + postfix_blankline_requested = 1; + ps.in_parameter_declaration = 0; + } + dec_ind = 0; + parse(lbrace); /* let parser know about this */ + if (ps.want_blank) /* put a blank before '{' if '{' is not at + * start of line */ + *e_code++ = ' '; + ps.want_blank = false; + *e_code++ = '{'; + ps.just_saw_decl = 0; + break; + + case rbrace: /* got a '}' */ + if (ps.p_stack[ps.tos] == decl && !ps.block_init) /* semicolons can be + * omitted in + * declarations */ + parse(semicolon); + if (ps.p_l_follow) {/* check for unclosed if, for, else. */ + diag2(1, "Unbalanced parens"); + ps.p_l_follow = 0; + sp_sw = false; + } + ps.just_saw_decl = 0; + ps.block_init_level--; + if (s_code != e_code && !ps.block_init) { /* '}' must be first on + * line */ + if (verbose) + diag2(0, "Line broken"); + dump_line(); + } + *e_code++ = '}'; + ps.want_blank = true; + ps.in_stmt = ps.ind_stmt = false; + if (ps.dec_nest > 0) { /* we are in multi-level structure + * declaration */ + dec_ind = di_stack[--ps.dec_nest]; + if (ps.dec_nest == 0 && !ps.in_parameter_declaration) + ps.just_saw_decl = 2; + ps.in_decl = true; + } + prefix_blankline_requested = 0; + parse(rbrace); /* let parser know about this */ + ps.search_brace = cuddle_else && ps.p_stack[ps.tos] == ifhead + && ps.il[ps.tos] >= ps.ind_level; + if (ps.tos <= 1 && blanklines_after_procs && ps.dec_nest <= 0) + postfix_blankline_requested = 1; + break; + + case swstmt: /* got keyword "switch" */ + sp_sw = true; + hd_type = swstmt; /* keep this for when we have seen the + * expression */ + goto copy_id; /* go move the token into buffer */ + + case sp_paren: /* token is if, while, for */ + sp_sw = true; /* the interesting stuff is done after the + * expression is scanned */ + hd_type = (*token == 'i' ? ifstmt : + (*token == 'w' ? whilestmt : forstmt)); + + /* + * remember the type of header for later use by parser + */ + goto copy_id; /* copy the token into line */ + + case sp_nparen: /* got else, do */ + ps.in_stmt = false; + if (*token == 'e') { + if (e_code != s_code && (!cuddle_else || e_code[-1] != '}')) { + if (verbose) + diag2(0, "Line broken"); + dump_line();/* make sure this starts a line */ + ps.want_blank = false; + } + force_nl = true;/* also, following stuff must go onto new line */ + last_else = 1; + parse(elselit); + } + else { + if (e_code != s_code) { /* make sure this starts a line */ + if (verbose) + diag2(0, "Line broken"); + dump_line(); + ps.want_blank = false; + } + force_nl = true;/* also, following stuff must go onto new line */ + last_else = 0; + parse(dolit); + } + goto copy_id; /* move the token into line */ + + case decl: /* we have a declaration type (int, register, + * etc.) */ + parse(decl); /* let parser worry about indentation */ + if (ps.last_token == rparen && ps.tos <= 1) { + ps.in_parameter_declaration = 1; + if (s_code != e_code) { + dump_line(); + ps.want_blank = 0; + } + } + if (ps.in_parameter_declaration && ps.indent_parameters && ps.dec_nest == 0) { + ps.ind_level = ps.i_l_follow = 1; + ps.ind_stmt = 0; + } + ps.in_or_st = true; /* this might be a structure or initialization + * declaration */ + ps.in_decl = ps.decl_on_line = true; + if ( /* !ps.in_or_st && */ ps.dec_nest <= 0) + ps.just_saw_decl = 2; + prefix_blankline_requested = 0; + for (i = 0; token[i++];); /* get length of token */ + + if (ps.ind_level == 0 || ps.dec_nest > 0) { + /* global variable or struct member in local variable */ + dec_ind = ps.decl_indent > 0 ? ps.decl_indent : i; + tabs_to_var = (use_tabs ? ps.decl_indent > 0 : 0); + } else { + /* local variable */ + dec_ind = ps.local_decl_indent > 0 ? ps.local_decl_indent : i; + tabs_to_var = (use_tabs ? ps.local_decl_indent > 0 : 0); + } + goto copy_id; + + case ident: /* got an identifier or constant */ + if (ps.in_decl) { /* if we are in a declaration, we must indent + * identifier */ + if (is_procname == 0 || !procnames_start_line) { + if (!ps.block_init) { + if (troff && !ps.dumped_decl_indent) { + if (ps.want_blank) + *e_code++ = ' '; + ps.want_blank = false; + sprintf(e_code, "\n.De %dp+\200p\n", dec_ind * 7); + ps.dumped_decl_indent = 1; + e_code += strlen(e_code); + } else { + int cur_dec_ind; + int pos, startpos; + + /* + * in order to get the tab math right for + * indentations that are not multiples of 8 we + * need to modify both startpos and dec_ind + * (cur_dec_ind) here by eight minus the + * remainder of the current starting column + * divided by eight. This seems to be a + * properly working fix + */ + startpos = e_code - s_code; + cur_dec_ind = dec_ind; + pos = startpos; + if ((ps.ind_level * ps.ind_size) % 8 != 0) { + pos += (ps.ind_level * ps.ind_size) % 8; + cur_dec_ind += (ps.ind_level * ps.ind_size) % 8; + } + + if (tabs_to_var) { + while ((pos & ~7) + 8 <= cur_dec_ind) { + CHECK_SIZE_CODE; + *e_code++ = '\t'; + pos = (pos & ~7) + 8; + } + } + while (pos < cur_dec_ind) { + CHECK_SIZE_CODE; + *e_code++ = ' '; + pos++; + } + if (ps.want_blank && e_code - s_code == startpos) + *e_code++ = ' '; + ps.want_blank = false; + } + } + } else { + if (ps.want_blank) + *e_code++ = ' '; + ps.want_blank = false; + if (dec_ind && s_code != e_code) + dump_line(); + dec_ind = 0; + } + } + else if (sp_sw && ps.p_l_follow == 0) { + sp_sw = false; + force_nl = true; + ps.last_u_d = true; + ps.in_stmt = false; + parse(hd_type); + } + copy_id: + if (ps.want_blank) + *e_code++ = ' '; + if (troff && ps.its_a_keyword) { + e_code = chfont(&bodyf, &keywordf, e_code); + for (t_ptr = token; *t_ptr; ++t_ptr) { + CHECK_SIZE_CODE; + *e_code++ = keywordf.allcaps && islower(*t_ptr) + ? toupper(*t_ptr) : *t_ptr; + } + e_code = chfont(&keywordf, &bodyf, e_code); + } + else + for (t_ptr = token; *t_ptr; ++t_ptr) { + CHECK_SIZE_CODE; + *e_code++ = *t_ptr; + } + ps.want_blank = true; + break; + + case period: /* treat a period kind of like a binary + * operation */ + *e_code++ = '.'; /* move the period into line */ + ps.want_blank = false; /* dont put a blank after a period */ + break; + + case comma: + ps.want_blank = (s_code != e_code); /* only put blank after comma + * if comma does not start the + * line */ + if (ps.in_decl && is_procname == 0 && !ps.block_init) + while ((e_code - s_code) < (dec_ind - 1)) { + CHECK_SIZE_CODE; + *e_code++ = ' '; + } + + *e_code++ = ','; + if (ps.p_l_follow == 0) { + if (ps.block_init_level <= 0) + ps.block_init = 0; + if (break_comma && (!ps.leave_comma || compute_code_target() + (e_code - s_code) > max_col - 8)) + force_nl = true; + } + break; + + case preesc: /* got the character '#' */ + if ((s_com != e_com) || + (s_lab != e_lab) || + (s_code != e_code)) + dump_line(); + *e_lab++ = '#'; /* move whole line to 'label' buffer */ + { + int in_comment = 0; + int com_start = 0; + char quote = 0; + int com_end = 0; + + while (*buf_ptr == ' ' || *buf_ptr == '\t') { + buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + } + while (*buf_ptr != '\n' || (in_comment && !had_eof)) { + CHECK_SIZE_LAB; + *e_lab = *buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + switch (*e_lab++) { + case BACKSLASH: + if (troff) + *e_lab++ = BACKSLASH; + if (!in_comment) { + *e_lab++ = *buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + } + break; + case '/': + if (*buf_ptr == '*' && !in_comment && !quote) { + in_comment = 1; + *e_lab++ = *buf_ptr++; + com_start = e_lab - s_lab - 2; + } + break; + case '"': + if (quote == '"') + quote = 0; + break; + case '\'': + if (quote == '\'') + quote = 0; + break; + case '*': + if (*buf_ptr == '/' && in_comment) { + in_comment = 0; + *e_lab++ = *buf_ptr++; + com_end = e_lab - s_lab; + } + break; + } + } + + while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t')) + e_lab--; + if (e_lab - s_lab == com_end && bp_save == 0) { /* comment on + * preprocessor line */ + if (sc_end == 0) /* if this is the first comment, we + * must set up the buffer */ + sc_end = &(save_com[0]); + else { + *sc_end++ = '\n'; /* add newline between + * comments */ + *sc_end++ = ' '; + --line_no; + } + bcopy(s_lab + com_start, sc_end, com_end - com_start); + sc_end += com_end - com_start; + if (sc_end >= &save_com[sc_size]) + abort(); + e_lab = s_lab + com_start; + while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t')) + e_lab--; + bp_save = buf_ptr; /* save current input buffer */ + be_save = buf_end; + buf_ptr = save_com; /* fix so that subsequent calls to + * lexi will take tokens out of + * save_com */ + *sc_end++ = ' '; /* add trailing blank, just in case */ + buf_end = sc_end; + sc_end = 0; + } + *e_lab = '\0'; /* null terminate line */ + ps.pcase = false; + } + + if (strncmp(s_lab, "#if", 3) == 0) { + if (blanklines_around_conditional_compilation) { + int c; + prefix_blankline_requested++; + while ((c = getc(input)) == '\n'); + ungetc(c, input); + } + if ((size_t)ifdef_level < sizeof(state_stack)/sizeof(state_stack[0])) { + match_state[ifdef_level].tos = -1; + state_stack[ifdef_level++] = ps; + } + else + diag2(1, "#if stack overflow"); + } + else if (strncmp(s_lab, "#else", 5) == 0) + if (ifdef_level <= 0) + diag2(1, "Unmatched #else"); + else { + match_state[ifdef_level - 1] = ps; + ps = state_stack[ifdef_level - 1]; + } + else if (strncmp(s_lab, "#endif", 6) == 0) { + if (ifdef_level <= 0) + diag2(1, "Unmatched #endif"); + else { + ifdef_level--; + +#ifdef undef + /* + * This match needs to be more intelligent before the + * message is useful + */ + if (match_state[ifdef_level].tos >= 0 + && bcmp(&ps, &match_state[ifdef_level], sizeof ps)) + diag2(0, "Syntactically inconsistent #ifdef alternatives"); +#endif + } + if (blanklines_around_conditional_compilation) { + postfix_blankline_requested++; + n_real_blanklines = 0; + } + } + break; /* subsequent processing of the newline + * character will cause the line to be printed */ + + case comment: /* we have gotten a / followed by * this is a biggie */ + if (flushed_nl) { /* we should force a broken line here */ + flushed_nl = false; + dump_line(); + ps.want_blank = false; /* dont insert blank at line start */ + force_nl = false; + } + pr_comment(); + break; + } /* end of big switch stmt */ + + *e_code = '\0'; /* make sure code section is null terminated */ + if (type_code != comment && type_code != newline && type_code != preesc) + ps.last_token = type_code; + } /* end of main while (1) loop */ +} + +/* + * copy input file to backup file if in_name is /blah/blah/blah/file, then + * backup file will be ".Bfile" then make the backup file the input and + * original input file the output + */ +static void +bakcopy(void) +{ + int n, + bakchn; + char buff[8 * 1024]; + const char *p; + + /* construct file name .Bfile */ + for (p = in_name; *p; p++); /* skip to end of string */ + while (p > in_name && *p != '/') /* find last '/' */ + p--; + if (*p == '/') + p++; + sprintf(bakfile, "%s.BAK", p); + + /* copy in_name to backup file */ + bakchn = creat(bakfile, 0600); + if (bakchn < 0) + err(1, "%s", bakfile); + while ((n = read(fileno(input), buff, sizeof buff)) != 0) + if (write(bakchn, buff, n) != n) + err(1, "%s", bakfile); + if (n < 0) + err(1, "%s", in_name); + close(bakchn); + fclose(input); + + /* re-open backup file as the input file */ + input = fopen(bakfile, "r"); + if (input == NULL) + err(1, "%s", bakfile); + /* now the original input file will be the output */ + output = fopen(in_name, "w"); + if (output == NULL) { + unlink(bakfile); + err(1, "%s", in_name); + } +} diff --git a/developer_cmds/indent/indent.h b/developer_cmds/indent/indent.h new file mode 100644 index 0000000..ac40f01 --- /dev/null +++ b/developer_cmds/indent/indent.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2001 Jens Schweikhardt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if 0 +__FBSDID("$FreeBSD: src/usr.bin/indent/indent.h,v 1.2 2002/03/30 17:10:20 dwmalone Exp $"); +#endif + +void addkey(char *, int); +int compute_code_target(void); +int compute_label_target(void); +int count_spaces(int, char *); +int lexi(void); +void diag2(int, const char *); +void diag3(int, const char *, int); +void diag4(int, const char *, int, int); +void dump_line(void); +void fill_buffer(void); +void parse(int); +void parsefont(struct fstate *, const char *); +void pr_comment(void); +void set_defaults(void); +void set_option(char *); +void set_profile(void); +void writefdef(struct fstate *f, int); diff --git a/developer_cmds/indent/indent_codes.h b/developer_cmds/indent/indent_codes.h new file mode 100644 index 0000000..008bf2b --- /dev/null +++ b/developer_cmds/indent/indent_codes.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)indent_codes.h 8.1 (Berkeley) 6/6/93 + * $FreeBSD: src/usr.bin/indent/indent_codes.h,v 1.2 2000/12/09 09:52:51 obrien Exp $ + */ + +#define newline 1 +#define lparen 2 +#define rparen 3 +#define unary_op 4 +#define binary_op 5 +#define postop 6 +#define question 7 +#define casestmt 8 +#define colon 9 +#define semicolon 10 +#define lbrace 11 +#define rbrace 12 +#define ident 13 +#define comma 14 +#define comment 15 +#define swstmt 16 +#define preesc 17 +#define form_feed 18 +#define decl 19 +#define sp_paren 20 +#define sp_nparen 21 +#define ifstmt 22 +#define whilestmt 23 +#define forstmt 24 +#define stmt 25 +#define stmtl 26 +#define elselit 27 +#define dolit 28 +#define dohead 29 +#define ifhead 30 +#define elsehead 31 +#define period 32 diff --git a/developer_cmds/indent/indent_globs.h b/developer_cmds/indent/indent_globs.h new file mode 100644 index 0000000..3ff82fa --- /dev/null +++ b/developer_cmds/indent/indent_globs.h @@ -0,0 +1,329 @@ +/* + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)indent_globs.h 8.1 (Berkeley) 6/6/93 + * $FreeBSD: src/usr.bin/indent/indent_globs.h,v 1.12 2010/03/31 17:05:30 avg Exp $ + */ + +#define BACKSLASH '\\' +#define bufsize 200 /* size of internal buffers */ +#define sc_size 5000 /* size of save_com buffer */ +#define label_offset 2 /* number of levels a label is placed to left + * of code */ + +#define tabsize 8 /* the size of a tab */ +#define tabmask 0177770 /* mask used when figuring length of lines + * with tabs */ + + +#define false 0 +#define true 1 + + +FILE *input; /* the fid for the input file */ +FILE *output; /* the output file */ + +#define CHECK_SIZE_CODE \ + if (e_code >= l_code) { \ + int nsize = l_code-s_code+400; \ + codebuf = (char *) realloc(codebuf, nsize); \ + if (codebuf == NULL) \ + err(1, NULL); \ + e_code = codebuf + (e_code-s_code) + 1; \ + l_code = codebuf + nsize - 5; \ + s_code = codebuf + 1; \ + } +#define CHECK_SIZE_COM \ + if (e_com >= l_com) { \ + int nsize = l_com-s_com+400; \ + combuf = (char *) realloc(combuf, nsize); \ + if (combuf == NULL) \ + err(1, NULL); \ + e_com = combuf + (e_com-s_com) + 1; \ + l_com = combuf + nsize - 5; \ + s_com = combuf + 1; \ + } +#define CHECK_SIZE_LAB \ + if (e_lab >= l_lab) { \ + int nsize = l_lab-s_lab+400; \ + labbuf = (char *) realloc(labbuf, nsize); \ + if (labbuf == NULL) \ + err(1, NULL); \ + e_lab = labbuf + (e_lab-s_lab) + 1; \ + l_lab = labbuf + nsize - 5; \ + s_lab = labbuf + 1; \ + } +#define CHECK_SIZE_TOKEN \ + if (e_token >= l_token) { \ + int nsize = l_token-s_token+400; \ + tokenbuf = (char *) realloc(tokenbuf, nsize); \ + if (tokenbuf == NULL) \ + err(1, NULL); \ + e_token = tokenbuf + (e_token-s_token) + 1; \ + l_token = tokenbuf + nsize - 5; \ + s_token = tokenbuf + 1; \ + } + +char *labbuf; /* buffer for label */ +char *s_lab; /* start ... */ +char *e_lab; /* .. and end of stored label */ +char *l_lab; /* limit of label buffer */ + +char *codebuf; /* buffer for code section */ +char *s_code; /* start ... */ +char *e_code; /* .. and end of stored code */ +char *l_code; /* limit of code section */ + +char *combuf; /* buffer for comments */ +char *s_com; /* start ... */ +char *e_com; /* ... and end of stored comments */ +char *l_com; /* limit of comment buffer */ + +#define token s_token +char *tokenbuf; /* the last token scanned */ +char *s_token; +char *e_token; +char *l_token; + +char *in_buffer; /* input buffer */ +char *in_buffer_limit; /* the end of the input buffer */ +char *buf_ptr; /* ptr to next character to be taken from + * in_buffer */ +char *buf_end; /* ptr to first after last char in in_buffer */ + +char save_com[sc_size]; /* input text is saved here when looking for + * the brace after an if, while, etc */ +char *sc_end; /* pointer into save_com buffer */ + +char *bp_save; /* saved value of buf_ptr when taking input + * from save_com */ +char *be_save; /* similarly saved value of buf_end */ + + +int found_err; +int pointer_as_binop; +int blanklines_after_declarations; +int blanklines_before_blockcomments; +int blanklines_after_procs; +int blanklines_around_conditional_compilation; +int swallow_optional_blanklines; +int n_real_blanklines; +int prefix_blankline_requested; +int postfix_blankline_requested; +int break_comma; /* when true and not in parens, break after a + * comma */ +int btype_2; /* when true, brace should be on same line as + * if, while, etc */ +float case_ind; /* indentation level to be used for a "case + * n:" */ +int code_lines; /* count of lines with code */ +int had_eof; /* set to true when input is exhausted */ +int line_no; /* the current line number. */ +int max_col; /* the maximum allowable line length */ +int verbose; /* when true, non-essential error messages are + * printed */ +int cuddle_else; /* true if else should cuddle up to '}' */ +int star_comment_cont; /* true iff comment continuation lines should + * have stars at the beginning of each line. */ +int comment_delimiter_on_blankline; +int troff; /* true iff were generating troff input */ +int procnames_start_line; /* if true, the names of procedures + * being defined get placed in column + * 1 (ie. a newline is placed between + * the type of the procedure and its + * name) */ +int proc_calls_space; /* If true, procedure calls look like: + * foo(bar) rather than foo (bar) */ +int format_block_comments; /* true if comments beginning with + * `/ * \n' are to be reformatted */ +int format_col1_comments; /* If comments which start in column 1 + * are to be magically reformatted + * (just like comments that begin in + * later columns) */ +int inhibit_formatting; /* true if INDENT OFF is in effect */ +int suppress_blanklines;/* set iff following blanklines should be + * suppressed */ +int continuation_indent;/* set to the indentation between the edge of + * code and continuation lines */ +int lineup_to_parens; /* if true, continued code within parens will + * be lined up to the open paren */ +int Bill_Shannon; /* true iff a blank should always be inserted + * after sizeof */ +int blanklines_after_declarations_at_proctop; /* This is vaguely + * similar to + * blanklines_after_decla + * rations except that + * it only applies to + * the first set of + * declarations in a + * procedure (just after + * the first '{') and it + * causes a blank line + * to be generated even + * if there are no + * declarations */ +int block_comment_max_col; +int extra_expression_indent; /* true if continuation lines from the + * expression part of "if(e)", + * "while(e)", "for(e;e;e)" should be + * indented an extra tab stop so that + * they don't conflict with the code + * that follows */ +int function_brace_split; /* split function declaration and + * brace onto separate lines */ +int use_tabs; /* set true to use tabs for spacing, + * false uses all spaces */ +int auto_typedefs; /* set true to recognize identifiers + * ending in "_t" like typedefs */ + +/* -troff font state information */ + +struct fstate { + char font[4]; + char size; + int allcaps:1; +}; +char *chfont(struct fstate *, struct fstate *, char *); + +struct fstate + keywordf, /* keyword font */ + stringf, /* string font */ + boxcomf, /* Box comment font */ + blkcomf, /* Block comment font */ + scomf, /* Same line comment font */ + bodyf; /* major body font */ + + +#define STACKSIZE 150 + +struct parser_state { + int last_token; + struct fstate cfont; /* Current font */ + int p_stack[STACKSIZE]; /* this is the parsers stack */ + int il[STACKSIZE]; /* this stack stores indentation levels */ + float cstk[STACKSIZE];/* used to store case stmt indentation levels */ + int box_com; /* set to true when we are in a "boxed" + * comment. In that case, the first non-blank + * char should be lined up with the / in / followed by * */ + int comment_delta, + n_comment_delta; + int cast_mask; /* indicates which close parens close off + * casts */ + int sizeof_mask; /* indicates which close parens close off + * sizeof''s */ + int block_init; /* true iff inside a block initialization */ + int block_init_level; /* The level of brace nesting in an + * initialization */ + int last_nl; /* this is true if the last thing scanned was + * a newline */ + int in_or_st; /* Will be true iff there has been a + * declarator (e.g. int or char) and no left + * paren since the last semicolon. When true, + * a '{' is starting a structure definition or + * an initialization list */ + int bl_line; /* set to 1 by dump_line if the line is blank */ + int col_1; /* set to true if the last token started in + * column 1 */ + int com_col; /* this is the column in which the current + * comment should start */ + int com_ind; /* the column in which comments to the right + * of code should start */ + int com_lines; /* the number of lines with comments, set by + * dump_line */ + int dec_nest; /* current nesting level for structure or init */ + int decl_com_ind; /* the column in which comments after + * declarations should be put */ + int decl_on_line; /* set to true if this line of code has part + * of a declaration on it */ + int i_l_follow; /* the level to which ind_level should be set + * after the current line is printed */ + int in_decl; /* set to true when we are in a declaration + * stmt. The processing of braces is then + * slightly different */ + int in_stmt; /* set to 1 while in a stmt */ + int ind_level; /* the current indentation level */ + int ind_size; /* the size of one indentation level */ + int ind_stmt; /* set to 1 if next line should have an extra + * indentation level because we are in the + * middle of a stmt */ + int last_u_d; /* set to true after scanning a token which + * forces a following operator to be unary */ + int leave_comma; /* if true, never break declarations after + * commas */ + int ljust_decl; /* true if declarations should be left + * justified */ + int out_coms; /* the number of comments processed, set by + * pr_comment */ + int out_lines; /* the number of lines written, set by + * dump_line */ + int p_l_follow; /* used to remember how to indent following + * statement */ + int paren_level; /* parenthesization level. used to indent + * within statements */ + short paren_indents[20]; /* column positions of each paren */ + int pcase; /* set to 1 if the current line label is a + * case. It is printed differently from a + * regular label */ + int search_brace; /* set to true by parse when it is necessary + * to buffer up all info up to the start of a + * stmt after an if, while, etc */ + int unindent_displace; /* comments not to the right of code + * will be placed this many + * indentation levels to the left of + * code */ + int use_ff; /* set to one if the current line should be + * terminated with a form feed */ + int want_blank; /* set to true when the following token should + * be prefixed by a blank. (Said prefixing is + * ignored in some cases.) */ + int else_if; /* True iff else if pairs should be handled + * specially */ + int decl_indent; /* column to indent declared identifiers to */ + int local_decl_indent; /* like decl_indent but for locals */ + int its_a_keyword; + int sizeof_keyword; + int dumped_decl_indent; + float case_indent; /* The distance to indent case labels from the + * switch statement */ + int in_parameter_declaration; + int indent_parameters; + int tos; /* pointer to top of stack */ + char procname[100]; /* The name of the current procedure */ + int just_saw_decl; +} ps; + +int ifdef_level; +int rparen_count; +struct parser_state state_stack[5]; +struct parser_state match_state[5]; diff --git a/developer_cmds/indent/io.c b/developer_cmds/indent/io.c new file mode 100644 index 0000000..d6fd5ef --- /dev/null +++ b/developer_cmds/indent/io.c @@ -0,0 +1,667 @@ +/* + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if 0 +#ifndef lint +static char sccsid[] = "@(#)io.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ +#endif + +#include +__FBSDID("$FreeBSD: src/usr.bin/indent/io.c,v 1.17 2011/12/30 11:02:40 uqs Exp $"); + +#include +#include +#include +#include +#include +#include "indent_globs.h" +#include "indent.h" + +int comment_open; +static int paren_target; +static int pad_output(int current, int target); + +void +dump_line(void) +{ /* dump_line is the routine that actually + * effects the printing of the new source. It + * prints the label section, followed by the + * code section with the appropriate nesting + * level, followed by any comments */ + int cur_col, + target_col = 1; + static int not_first_line; + + if (ps.procname[0]) { + if (troff) { + if (comment_open) { + comment_open = 0; + fprintf(output, ".*/\n"); + } + fprintf(output, ".Pr \"%s\"\n", ps.procname); + } + ps.ind_level = 0; + ps.procname[0] = 0; + } + if (s_code == e_code && s_lab == e_lab && s_com == e_com) { + if (suppress_blanklines > 0) + suppress_blanklines--; + else { + ps.bl_line = true; + n_real_blanklines++; + } + } + else if (!inhibit_formatting) { + suppress_blanklines = 0; + ps.bl_line = false; + if (prefix_blankline_requested && not_first_line) { + if (swallow_optional_blanklines) { + if (n_real_blanklines == 1) + n_real_blanklines = 0; + } + else { + if (n_real_blanklines == 0) + n_real_blanklines = 1; + } + } + while (--n_real_blanklines >= 0) + putc('\n', output); + n_real_blanklines = 0; + if (ps.ind_level == 0) + ps.ind_stmt = 0; /* this is a class A kludge. dont do + * additional statement indentation if we are + * at bracket level 0 */ + + if (e_lab != s_lab || e_code != s_code) + ++code_lines; /* keep count of lines with code */ + + + if (e_lab != s_lab) { /* print lab, if any */ + if (comment_open) { + comment_open = 0; + fprintf(output, ".*/\n"); + } + while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t')) + e_lab--; + cur_col = pad_output(1, compute_label_target()); + if (s_lab[0] == '#' && (strncmp(s_lab, "#else", 5) == 0 + || strncmp(s_lab, "#endif", 6) == 0)) { + char *s = s_lab; + if (e_lab[-1] == '\n') e_lab--; + do putc(*s++, output); + while (s < e_lab && 'a' <= *s && *s<='z'); + while ((*s == ' ' || *s == '\t') && s < e_lab) + s++; + if (s < e_lab) + fprintf(output, s[0]=='/' && s[1]=='*' ? "\t%.*s" : "\t/* %.*s */", + (int)(e_lab - s), s); + } + else fprintf(output, "%.*s", (int)(e_lab - s_lab), s_lab); + cur_col = count_spaces(cur_col, s_lab); + } + else + cur_col = 1; /* there is no label section */ + + ps.pcase = false; + + if (s_code != e_code) { /* print code section, if any */ + char *p; + + if (comment_open) { + comment_open = 0; + fprintf(output, ".*/\n"); + } + target_col = compute_code_target(); + { + int i; + + for (i = 0; i < ps.p_l_follow; i++) + if (ps.paren_indents[i] >= 0) + ps.paren_indents[i] = -(ps.paren_indents[i] + target_col); + } + cur_col = pad_output(cur_col, target_col); + for (p = s_code; p < e_code; p++) + if (*p == (char) 0200) + fprintf(output, "%d", target_col * 7); + else + putc(*p, output); + cur_col = count_spaces(cur_col, s_code); + } + if (s_com != e_com) { + if (troff) { + int all_here = 0; + char *p; + + if (e_com[-1] == '/' && e_com[-2] == '*') + e_com -= 2, all_here++; + while (e_com > s_com && e_com[-1] == ' ') + e_com--; + *e_com = 0; + p = s_com; + while (*p == ' ') + p++; + if (p[0] == '/' && p[1] == '*') + p += 2, all_here++; + else if (p[0] == '*') + p += p[1] == '/' ? 2 : 1; + while (*p == ' ') + p++; + if (*p == 0) + goto inhibit_newline; + if (comment_open < 2 && ps.box_com) { + comment_open = 0; + fprintf(output, ".*/\n"); + } + if (comment_open == 0) { + if ('a' <= *p && *p <= 'z') + *p = *p + 'A' - 'a'; + if (e_com - p < 50 && all_here == 2) { + char *follow = p; + fprintf(output, "\n.nr C! \\w\1"); + while (follow < e_com) { + switch (*follow) { + case '\n': + putc(' ', output); + case 1: + break; + case '\\': + putc('\\', output); + default: + putc(*follow, output); + } + follow++; + } + putc(1, output); + } + fprintf(output, "\n./* %dp %d %dp\n", + ps.com_col * 7, + (s_code != e_code || s_lab != e_lab) - ps.box_com, + target_col * 7); + } + comment_open = 1 + ps.box_com; + while (*p) { + if (*p == BACKSLASH) + putc(BACKSLASH, output); + putc(*p++, output); + } + } + else { /* print comment, if any */ + int target = ps.com_col; + char *com_st = s_com; + + target += ps.comment_delta; + while (*com_st == '\t') + com_st++, target += 8; /* ? */ + while (target <= 0) + if (*com_st == ' ') + target++, com_st++; + else if (*com_st == '\t') + target = ((target - 1) & ~7) + 9, com_st++; + else + target = 1; + if (cur_col > target) { /* if comment can't fit on this line, + * put it on next line */ + putc('\n', output); + cur_col = 1; + ++ps.out_lines; + } + while (e_com > com_st && isspace(e_com[-1])) + e_com--; + cur_col = pad_output(cur_col, target); + if (!ps.box_com) { + if (star_comment_cont && (com_st[1] != '*' || e_com <= com_st + 1)) { + if (com_st[1] == ' ' && com_st[0] == ' ' && e_com > com_st + 1) + com_st[1] = '*'; + else + fwrite(" * ", com_st[0] == '\t' ? 2 : com_st[0] == '*' ? 1 : 3, 1, output); + } + } + fwrite(com_st, e_com - com_st, 1, output); + ps.comment_delta = ps.n_comment_delta; + cur_col = count_spaces(cur_col, com_st); + ++ps.com_lines; /* count lines with comments */ + } + } + if (ps.use_ff) + putc('\014', output); + else + putc('\n', output); +inhibit_newline: + ++ps.out_lines; + if (ps.just_saw_decl == 1 && blanklines_after_declarations) { + prefix_blankline_requested = 1; + ps.just_saw_decl = 0; + } + else + prefix_blankline_requested = postfix_blankline_requested; + postfix_blankline_requested = 0; + } + ps.decl_on_line = ps.in_decl; /* if we are in the middle of a + * declaration, remember that fact for + * proper comment indentation */ + ps.ind_stmt = ps.in_stmt & ~ps.in_decl; /* next line should be + * indented if we have not + * completed this stmt and if + * we are not in the middle of + * a declaration */ + ps.use_ff = false; + ps.dumped_decl_indent = 0; + *(e_lab = s_lab) = '\0'; /* reset buffers */ + *(e_code = s_code) = '\0'; + *(e_com = s_com) = '\0'; + ps.ind_level = ps.i_l_follow; + ps.paren_level = ps.p_l_follow; + paren_target = -ps.paren_indents[ps.paren_level - 1]; + not_first_line = 1; +} + +int +compute_code_target(void) +{ + int target_col = ps.ind_size * ps.ind_level + 1; + + if (ps.paren_level) + if (!lineup_to_parens) + target_col += continuation_indent + * (2 * continuation_indent == ps.ind_size ? 1 : ps.paren_level); + else { + int w; + int t = paren_target; + + if ((w = count_spaces(t, s_code) - max_col) > 0 + && count_spaces(target_col, s_code) <= max_col) { + t -= w + 1; + if (t > target_col) + target_col = t; + } + else + target_col = t; + } + else if (ps.ind_stmt) + target_col += continuation_indent; + return target_col; +} + +int +compute_label_target(void) +{ + return + ps.pcase ? (int) (case_ind * ps.ind_size) + 1 + : *s_lab == '#' ? 1 + : ps.ind_size * (ps.ind_level - label_offset) + 1; +} + + +/* + * Copyright (C) 1976 by the Board of Trustees of the University of Illinois + * + * All rights reserved + * + * + * NAME: fill_buffer + * + * FUNCTION: Reads one block of input into input_buffer + * + * HISTORY: initial coding November 1976 D A Willcox of CAC 1/7/77 A + * Willcox of CAC Added check for switch back to partly full input + * buffer from temporary buffer + * + */ +void +fill_buffer(void) +{ /* this routine reads stuff from the input */ + char *p; + int i; + FILE *f = input; + + if (bp_save != 0) { /* there is a partly filled input buffer left */ + buf_ptr = bp_save; /* dont read anything, just switch buffers */ + buf_end = be_save; + bp_save = be_save = 0; + if (buf_ptr < buf_end) + return; /* only return if there is really something in + * this buffer */ + } + for (p = in_buffer;;) { + if (p >= in_buffer_limit) { + int size = (in_buffer_limit - in_buffer) * 2 + 10; + int offset = p - in_buffer; + in_buffer = realloc(in_buffer, size); + if (in_buffer == NULL) + errx(1, "input line too long"); + p = in_buffer + offset; + in_buffer_limit = in_buffer + size - 2; + } + if ((i = getc(f)) == EOF) { + *p++ = ' '; + *p++ = '\n'; + had_eof = true; + break; + } + *p++ = i; + if (i == '\n') + break; + } + buf_ptr = in_buffer; + buf_end = p; + if (p[-2] == '/' && p[-3] == '*') { + if (in_buffer[3] == 'I' && strncmp(in_buffer, "/**INDENT**", 11) == 0) + fill_buffer(); /* flush indent error message */ + else { + int com = 0; + + p = in_buffer; + while (*p == ' ' || *p == '\t') + p++; + if (*p == '/' && p[1] == '*') { + p += 2; + while (*p == ' ' || *p == '\t') + p++; + if (p[0] == 'I' && p[1] == 'N' && p[2] == 'D' && p[3] == 'E' + && p[4] == 'N' && p[5] == 'T') { + p += 6; + while (*p == ' ' || *p == '\t') + p++; + if (*p == '*') + com = 1; + else if (*p == 'O') { + if (*++p == 'N') + p++, com = 1; + else if (*p == 'F' && *++p == 'F') + p++, com = 2; + } + while (*p == ' ' || *p == '\t') + p++; + if (p[0] == '*' && p[1] == '/' && p[2] == '\n' && com) { + if (s_com != e_com || s_lab != e_lab || s_code != e_code) + dump_line(); + if (!(inhibit_formatting = com - 1)) { + n_real_blanklines = 0; + postfix_blankline_requested = 0; + prefix_blankline_requested = 0; + suppress_blanklines = 1; + } + } + } + } + } + } + if (inhibit_formatting) { + p = in_buffer; + do + putc(*p, output); + while (*p++ != '\n'); + } +} + +/* + * Copyright (C) 1976 by the Board of Trustees of the University of Illinois + * + * All rights reserved + * + * + * NAME: pad_output + * + * FUNCTION: Writes tabs and spaces to move the current column up to the desired + * position. + * + * ALGORITHM: Put tabs and/or blanks into pobuf, then write pobuf. + * + * PARAMETERS: current integer The current column target + * nteger The desired column + * + * RETURNS: Integer value of the new column. (If current >= target, no action is + * taken, and current is returned. + * + * GLOBALS: None + * + * CALLS: write (sys) + * + * CALLED BY: dump_line + * + * HISTORY: initial coding November 1976 D A Willcox of CAC + * + */ +static int +pad_output(int current, int target) + /* writes tabs and blanks (if necessary) to + * get the current output position up to the + * target column */ + /* current: the current column value */ + /* target: position we want it at */ +{ + int curr; /* internal column pointer */ + int tcur; + + if (troff) + fprintf(output, "\\h'|%dp'", (target - 1) * 7); + else { + if (current >= target) + return (current); /* line is already long enough */ + curr = current; + if (use_tabs) { + while ((tcur = ((curr - 1) & tabmask) + tabsize + 1) <= target) { + putc('\t', output); + curr = tcur; + } + } + while (curr++ < target) + putc(' ', output); /* pad with final blanks */ + } + return (target); +} + +/* + * Copyright (C) 1976 by the Board of Trustees of the University of Illinois + * + * All rights reserved + * + * + * NAME: count_spaces + * + * FUNCTION: Find out where printing of a given string will leave the current + * character position on output. + * + * ALGORITHM: Run thru input string and add appropriate values to current + * position. + * + * RETURNS: Integer value of position after printing "buffer" starting in column + * "current". + * + * HISTORY: initial coding November 1976 D A Willcox of CAC + * + */ +int +count_spaces(int current, char *buffer) +/* + * this routine figures out where the character position will be after + * printing the text in buffer starting at column "current" + */ +{ + char *buf; /* used to look thru buffer */ + int cur; /* current character counter */ + + cur = current; + + for (buf = buffer; *buf != '\0'; ++buf) { + switch (*buf) { + + case '\n': + case 014: /* form feed */ + cur = 1; + break; + + case '\t': + cur = ((cur - 1) & tabmask) + tabsize + 1; + break; + + case 010: /* backspace */ + --cur; + break; + + default: + ++cur; + break; + } /* end of switch */ + } /* end of for loop */ + return (cur); +} + +void +diag4(int level, const char *msg, int a, int b) +{ + if (level) + found_err = 1; + if (output == stdout) { + fprintf(stdout, "/**INDENT** %s@%d: ", level == 0 ? "Warning" : "Error", line_no); + fprintf(stdout, msg, a, b); + fprintf(stdout, " */\n"); + } + else { + fprintf(stderr, "%s@%d: ", level == 0 ? "Warning" : "Error", line_no); + fprintf(stderr, msg, a, b); + fprintf(stderr, "\n"); + } +} + +void +diag3(int level, const char *msg, int a) +{ + if (level) + found_err = 1; + if (output == stdout) { + fprintf(stdout, "/**INDENT** %s@%d: ", level == 0 ? "Warning" : "Error", line_no); + fprintf(stdout, msg, a); + fprintf(stdout, " */\n"); + } + else { + fprintf(stderr, "%s@%d: ", level == 0 ? "Warning" : "Error", line_no); + fprintf(stderr, msg, a); + fprintf(stderr, "\n"); + } +} + +void +diag2(int level, const char *msg) +{ + if (level) + found_err = 1; + if (output == stdout) { + fprintf(stdout, "/**INDENT** %s@%d: ", level == 0 ? "Warning" : "Error", line_no); + fprintf(stdout, "%s", msg); + fprintf(stdout, " */\n"); + } + else { + fprintf(stderr, "%s@%d: ", level == 0 ? "Warning" : "Error", line_no); + fprintf(stderr, "%s", msg); + fprintf(stderr, "\n"); + } +} + +void +writefdef(struct fstate *f, int nm) +{ + fprintf(output, ".ds f%c %s\n.nr s%c %d\n", + nm, f->font, nm, f->size); +} + +char * +chfont(struct fstate *of, struct fstate *nf, char *s) +{ + if (of->font[0] != nf->font[0] + || of->font[1] != nf->font[1]) { + *s++ = '\\'; + *s++ = 'f'; + if (nf->font[1]) { + *s++ = '('; + *s++ = nf->font[0]; + *s++ = nf->font[1]; + } + else + *s++ = nf->font[0]; + } + if (nf->size != of->size) { + *s++ = '\\'; + *s++ = 's'; + if (nf->size < of->size) { + *s++ = '-'; + *s++ = '0' + of->size - nf->size; + } + else { + *s++ = '+'; + *s++ = '0' + nf->size - of->size; + } + } + return s; +} + +void +parsefont(struct fstate *f, const char *s0) +{ + const char *s = s0; + int sizedelta = 0; + + bzero(f, sizeof *f); + while (*s) { + if (isdigit(*s)) + f->size = f->size * 10 + *s - '0'; + else if (isupper(*s)) + if (f->font[0]) + f->font[1] = *s; + else + f->font[0] = *s; + else if (*s == 'c') + f->allcaps = 1; + else if (*s == '+') + sizedelta++; + else if (*s == '-') + sizedelta--; + else { + errx(1, "bad font specification: %s", s0); + } + s++; + } + if (f->font[0] == 0) + f->font[0] = 'R'; + if (bodyf.size == 0) + bodyf.size = 11; + if (f->size == 0) + f->size = bodyf.size + sizedelta; + else if (sizedelta > 0) + f->size += bodyf.size; + else + f->size = bodyf.size - f->size; +} diff --git a/developer_cmds/indent/lexi.c b/developer_cmds/indent/lexi.c new file mode 100644 index 0000000..fbee368 --- /dev/null +++ b/developer_cmds/indent/lexi.c @@ -0,0 +1,608 @@ +/* + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if 0 +#ifndef lint +static char sccsid[] = "@(#)lexi.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ +#endif +#include +__FBSDID("$FreeBSD: src/usr.bin/indent/lexi.c,v 1.21 2010/04/15 21:41:07 avg Exp $"); + +/* + * Here we have the token scanner for indent. It scans off one token and puts + * it in the global variable "token". It returns a code, indicating the type + * of token scanned. + */ + +#include +#include +#include +#include +#include +#include "indent_globs.h" +#include "indent_codes.h" +#include "indent.h" + +#define alphanum 1 +#define opchar 3 + +struct templ { + const char *rwd; + int rwcode; +}; + +struct templ specials[1000] = +{ + {"switch", 1}, + {"case", 2}, + {"break", 0}, + {"struct", 3}, + {"union", 3}, + {"enum", 3}, + {"default", 2}, + {"int", 4}, + {"char", 4}, + {"float", 4}, + {"double", 4}, + {"long", 4}, + {"short", 4}, + {"typdef", 4}, + {"unsigned", 4}, + {"register", 4}, + {"static", 4}, + {"global", 4}, + {"extern", 4}, + {"void", 4}, + {"const", 4}, + {"volatile", 4}, + {"goto", 0}, + {"return", 0}, + {"if", 5}, + {"while", 5}, + {"for", 5}, + {"else", 6}, + {"do", 6}, + {"sizeof", 7}, + {0, 0} +}; + +char chartype[128] = +{ /* this is used to facilitate the decision of + * what type (alphanumeric, operator) each + * character is */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3, 0, 0, 1, 3, 3, 0, + 0, 0, 3, 3, 0, 3, 0, 3, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 0, 0, 3, 3, 3, 3, + 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 0, 0, 3, 1, + 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 3, 0, 3, 0 +}; + +int +lexi(void) +{ + int unary_delim; /* this is set to 1 if the current token + * forces a following operator to be unary */ + static int last_code; /* the last token type returned */ + static int l_struct; /* set to 1 if the last token was 'struct' */ + int code; /* internal code to be returned */ + char qchar; /* the delimiter character for a string */ + + e_token = s_token; /* point to start of place to save token */ + unary_delim = false; + ps.col_1 = ps.last_nl; /* tell world that this token started in + * column 1 iff the last thing scanned was nl */ + ps.last_nl = false; + + while (*buf_ptr == ' ' || *buf_ptr == '\t') { /* get rid of blanks */ + ps.col_1 = false; /* leading blanks imply token is not in column + * 1 */ + if (++buf_ptr >= buf_end) + fill_buffer(); + } + + /* Scan an alphanumeric token */ + if (chartype[(int)*buf_ptr] == alphanum || (buf_ptr[0] == '.' && isdigit(buf_ptr[1]))) { + /* + * we have a character or number + */ + const char *j; /* used for searching thru list of + * + * reserved words */ + struct templ *p; + + if (isdigit(*buf_ptr) || (buf_ptr[0] == '.' && isdigit(buf_ptr[1]))) { + int seendot = 0, + seenexp = 0, + seensfx = 0; + if (*buf_ptr == '0' && + (buf_ptr[1] == 'x' || buf_ptr[1] == 'X')) { + *e_token++ = *buf_ptr++; + *e_token++ = *buf_ptr++; + while (isxdigit(*buf_ptr)) { + CHECK_SIZE_TOKEN; + *e_token++ = *buf_ptr++; + } + } + else + while (1) { + if (*buf_ptr == '.') { + if (seendot) + break; + else + seendot++; + } + CHECK_SIZE_TOKEN; + *e_token++ = *buf_ptr++; + if (!isdigit(*buf_ptr) && *buf_ptr != '.') { + if ((*buf_ptr != 'E' && *buf_ptr != 'e') || seenexp) + break; + else { + seenexp++; + seendot++; + CHECK_SIZE_TOKEN; + *e_token++ = *buf_ptr++; + if (*buf_ptr == '+' || *buf_ptr == '-') + *e_token++ = *buf_ptr++; + } + } + } + while (1) { + if (!(seensfx & 1) && + (*buf_ptr == 'U' || *buf_ptr == 'u')) { + CHECK_SIZE_TOKEN; + *e_token++ = *buf_ptr++; + seensfx |= 1; + continue; + } + if (!(seensfx & 2) && + (*buf_ptr == 'L' || *buf_ptr == 'l')) { + CHECK_SIZE_TOKEN; + if (buf_ptr[1] == buf_ptr[0]) + *e_token++ = *buf_ptr++; + *e_token++ = *buf_ptr++; + seensfx |= 2; + continue; + } + break; + } + } + else + while (chartype[(int)*buf_ptr] == alphanum || *buf_ptr == BACKSLASH) { + /* fill_buffer() terminates buffer with newline */ + if (*buf_ptr == BACKSLASH) { + if (*(buf_ptr + 1) == '\n') { + buf_ptr += 2; + if (buf_ptr >= buf_end) + fill_buffer(); + } else + break; + } + CHECK_SIZE_TOKEN; + /* copy it over */ + *e_token++ = *buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + } + *e_token++ = '\0'; + while (*buf_ptr == ' ' || *buf_ptr == '\t') { /* get rid of blanks */ + if (++buf_ptr >= buf_end) + fill_buffer(); + } + ps.its_a_keyword = false; + ps.sizeof_keyword = false; + if (l_struct && !ps.p_l_follow) { + /* if last token was 'struct' and we're not + * in parentheses, then this token + * should be treated as a declaration */ + l_struct = false; + last_code = ident; + ps.last_u_d = true; + return (decl); + } + ps.last_u_d = l_struct; /* Operator after identifier is binary + * unless last token was 'struct' */ + l_struct = false; + last_code = ident; /* Remember that this is the code we will + * return */ + + if (auto_typedefs) { + const char *q = s_token; + size_t q_len = strlen(q); + /* Check if we have an "_t" in the end */ + if (q_len > 2 && + (strcmp(q + q_len - 2, "_t") == 0)) { + ps.its_a_keyword = true; + ps.last_u_d = true; + goto found_auto_typedef; + } + } + + /* + * This loop will check if the token is a keyword. + */ + for (p = specials; (j = p->rwd) != 0; p++) { + const char *q = s_token; /* point at scanned token */ + if (*j++ != *q++ || *j++ != *q++) + continue; /* This test depends on the fact that + * identifiers are always at least 1 character + * long (ie. the first two bytes of the + * identifier are always meaningful) */ + if (q[-1] == 0) + break; /* If its a one-character identifier */ + while (*q++ == *j) + if (*j++ == 0) + goto found_keyword; /* I wish that C had a multi-level + * break... */ + } + if (p->rwd) { /* we have a keyword */ + found_keyword: + ps.its_a_keyword = true; + ps.last_u_d = true; + switch (p->rwcode) { + case 1: /* it is a switch */ + return (swstmt); + case 2: /* a case or default */ + return (casestmt); + + case 3: /* a "struct" */ + /* + * Next time around, we will want to know that we have had a + * 'struct' + */ + l_struct = true; + /* FALLTHROUGH */ + + case 4: /* one of the declaration keywords */ + found_auto_typedef: + if (ps.p_l_follow) { + ps.cast_mask |= (1 << ps.p_l_follow) & ~ps.sizeof_mask; + break; /* inside parens: cast, param list or sizeof */ + } + last_code = decl; + return (decl); + + case 5: /* if, while, for */ + return (sp_paren); + + case 6: /* do, else */ + return (sp_nparen); + + case 7: + ps.sizeof_keyword = true; + default: /* all others are treated like any other + * identifier */ + return (ident); + } /* end of switch */ + } /* end of if (found_it) */ + if (*buf_ptr == '(' && ps.tos <= 1 && ps.ind_level == 0) { + char *tp = buf_ptr; + while (tp < buf_end) + if (*tp++ == ')' && (*tp == ';' || *tp == ',')) + goto not_proc; + strncpy(ps.procname, token, sizeof ps.procname - 1); + ps.in_parameter_declaration = 1; + rparen_count = 1; + not_proc:; + } + /* + * The following hack attempts to guess whether or not the current + * token is in fact a declaration keyword -- one that has been + * typedefd + */ + if (((*buf_ptr == '*' && buf_ptr[1] != '=') || isalpha(*buf_ptr) || *buf_ptr == '_') + && !ps.p_l_follow + && !ps.block_init + && (ps.last_token == rparen || ps.last_token == semicolon || + ps.last_token == decl || + ps.last_token == lbrace || ps.last_token == rbrace)) { + ps.its_a_keyword = true; + ps.last_u_d = true; + last_code = decl; + return decl; + } + if (last_code == decl) /* if this is a declared variable, then + * following sign is unary */ + ps.last_u_d = true; /* will make "int a -1" work */ + last_code = ident; + return (ident); /* the ident is not in the list */ + } /* end of procesing for alpanum character */ + + /* Scan a non-alphanumeric token */ + + *e_token++ = *buf_ptr; /* if it is only a one-character token, it is + * moved here */ + *e_token = '\0'; + if (++buf_ptr >= buf_end) + fill_buffer(); + + switch (*token) { + case '\n': + unary_delim = ps.last_u_d; + ps.last_nl = true; /* remember that we just had a newline */ + code = (had_eof ? 0 : newline); + + /* + * if data has been exhausted, the newline is a dummy, and we should + * return code to stop + */ + break; + + case '\'': /* start of quoted character */ + case '"': /* start of string */ + qchar = *token; + if (troff) { + e_token[-1] = '`'; + if (qchar == '"') + *e_token++ = '`'; + e_token = chfont(&bodyf, &stringf, e_token); + } + do { /* copy the string */ + while (1) { /* move one character or [/] */ + if (*buf_ptr == '\n') { + diag2(1, "Unterminated literal"); + goto stop_lit; + } + CHECK_SIZE_TOKEN; /* Only have to do this once in this loop, + * since CHECK_SIZE guarantees that there + * are at least 5 entries left */ + *e_token = *buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + if (*e_token == BACKSLASH) { /* if escape, copy extra char */ + if (*buf_ptr == '\n') /* check for escaped newline */ + ++line_no; + if (troff) { + *++e_token = BACKSLASH; + if (*buf_ptr == BACKSLASH) + *++e_token = BACKSLASH; + } + *++e_token = *buf_ptr++; + ++e_token; /* we must increment this again because we + * copied two chars */ + if (buf_ptr >= buf_end) + fill_buffer(); + } + else + break; /* we copied one character */ + } /* end of while (1) */ + } while (*e_token++ != qchar); + if (troff) { + e_token = chfont(&stringf, &bodyf, e_token - 1); + if (qchar == '"') + *e_token++ = '\''; + } +stop_lit: + code = ident; + break; + + case ('('): + case ('['): + unary_delim = true; + code = lparen; + break; + + case (')'): + case (']'): + code = rparen; + break; + + case '#': + unary_delim = ps.last_u_d; + code = preesc; + break; + + case '?': + unary_delim = true; + code = question; + break; + + case (':'): + code = colon; + unary_delim = true; + break; + + case (';'): + unary_delim = true; + code = semicolon; + break; + + case ('{'): + unary_delim = true; + + /* + * if (ps.in_or_st) ps.block_init = 1; + */ + /* ? code = ps.block_init ? lparen : lbrace; */ + code = lbrace; + break; + + case ('}'): + unary_delim = true; + /* ? code = ps.block_init ? rparen : rbrace; */ + code = rbrace; + break; + + case 014: /* a form feed */ + unary_delim = ps.last_u_d; + ps.last_nl = true; /* remember this so we can set 'ps.col_1' + * right */ + code = form_feed; + break; + + case (','): + unary_delim = true; + code = comma; + break; + + case '.': + unary_delim = false; + code = period; + break; + + case '-': + case '+': /* check for -, +, --, ++ */ + code = (ps.last_u_d ? unary_op : binary_op); + unary_delim = true; + + if (*buf_ptr == token[0]) { + /* check for doubled character */ + *e_token++ = *buf_ptr++; + /* buffer overflow will be checked at end of loop */ + if (last_code == ident || last_code == rparen) { + code = (ps.last_u_d ? unary_op : postop); + /* check for following ++ or -- */ + unary_delim = false; + } + } + else if (*buf_ptr == '=') + /* check for operator += */ + *e_token++ = *buf_ptr++; + else if (*buf_ptr == '>') { + /* check for operator -> */ + *e_token++ = *buf_ptr++; + if (!pointer_as_binop) { + unary_delim = false; + code = unary_op; + ps.want_blank = false; + } + } + break; /* buffer overflow will be checked at end of + * switch */ + + case '=': + if (ps.in_or_st) + ps.block_init = 1; +#ifdef undef + if (chartype[*buf_ptr] == opchar) { /* we have two char assignment */ + e_token[-1] = *buf_ptr++; + if ((e_token[-1] == '<' || e_token[-1] == '>') && e_token[-1] == *buf_ptr) + *e_token++ = *buf_ptr++; + *e_token++ = '='; /* Flip =+ to += */ + *e_token = 0; + } +#else + if (*buf_ptr == '=') {/* == */ + *e_token++ = '='; /* Flip =+ to += */ + buf_ptr++; + *e_token = 0; + } +#endif + code = binary_op; + unary_delim = true; + break; + /* can drop thru!!! */ + + case '>': + case '<': + case '!': /* ops like <, <<, <=, !=, etc */ + if (*buf_ptr == '>' || *buf_ptr == '<' || *buf_ptr == '=') { + *e_token++ = *buf_ptr; + if (++buf_ptr >= buf_end) + fill_buffer(); + } + if (*buf_ptr == '=') + *e_token++ = *buf_ptr++; + code = (ps.last_u_d ? unary_op : binary_op); + unary_delim = true; + break; + + default: + if (token[0] == '/' && *buf_ptr == '*') { + /* it is start of comment */ + *e_token++ = '*'; + + if (++buf_ptr >= buf_end) + fill_buffer(); + + code = comment; + unary_delim = ps.last_u_d; + break; + } + while (*(e_token - 1) == *buf_ptr || *buf_ptr == '=') { + /* + * handle ||, &&, etc, and also things as in int *****i + */ + *e_token++ = *buf_ptr; + if (++buf_ptr >= buf_end) + fill_buffer(); + } + code = (ps.last_u_d ? unary_op : binary_op); + unary_delim = true; + + + } /* end of switch */ + if (code != newline) { + l_struct = false; + last_code = code; + } + if (buf_ptr >= buf_end) /* check for input buffer empty */ + fill_buffer(); + ps.last_u_d = unary_delim; + *e_token = '\0'; /* null terminate the token */ + return (code); +} + +/* + * Add the given keyword to the keyword table, using val as the keyword type + */ +void +addkey(char *key, int val) +{ + struct templ *p = specials; + while (p->rwd) + if (p->rwd[0] == key[0] && strcmp(p->rwd, key) == 0) + return; + else + p++; + if (p >= specials + sizeof specials / sizeof specials[0]) + return; /* For now, table overflows are silently + * ignored */ + p->rwd = key; + p->rwcode = val; + p[1].rwd = 0; + p[1].rwcode = 0; +} diff --git a/developer_cmds/indent/parse.c b/developer_cmds/indent/parse.c new file mode 100644 index 0000000..7720ff1 --- /dev/null +++ b/developer_cmds/indent/parse.c @@ -0,0 +1,332 @@ +/* + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if 0 +#ifndef lint +static char sccsid[] = "@(#)parse.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ +#endif + +#include +__FBSDID("$FreeBSD: src/usr.bin/indent/parse.c,v 1.10 2003/06/15 09:28:17 charnier Exp $"); + +#include +#include "indent_globs.h" +#include "indent_codes.h" +#include "indent.h" + +static void reduce(void); + +void +parse(int tk) /* tk: the code for the construct scanned */ +{ + int i; + +#ifdef debug + printf("%2d - %s\n", tk, token); +#endif + + while (ps.p_stack[ps.tos] == ifhead && tk != elselit) { + /* true if we have an if without an else */ + ps.p_stack[ps.tos] = stmt; /* apply the if(..) stmt ::= stmt + * reduction */ + reduce(); /* see if this allows any reduction */ + } + + + switch (tk) { /* go on and figure out what to do with the + * input */ + + case decl: /* scanned a declaration word */ + ps.search_brace = btype_2; + /* indicate that following brace should be on same line */ + if (ps.p_stack[ps.tos] != decl) { /* only put one declaration + * onto stack */ + break_comma = true; /* while in declaration, newline should be + * forced after comma */ + ps.p_stack[++ps.tos] = decl; + ps.il[ps.tos] = ps.i_l_follow; + + if (ps.ljust_decl) {/* only do if we want left justified + * declarations */ + ps.ind_level = 0; + for (i = ps.tos - 1; i > 0; --i) + if (ps.p_stack[i] == decl) + ++ps.ind_level; /* indentation is number of + * declaration levels deep we are */ + ps.i_l_follow = ps.ind_level; + } + } + break; + + case ifstmt: /* scanned if (...) */ + if (ps.p_stack[ps.tos] == elsehead && ps.else_if) /* "else if ..." */ + ps.i_l_follow = ps.il[ps.tos]; + case dolit: /* 'do' */ + case forstmt: /* for (...) */ + ps.p_stack[++ps.tos] = tk; + ps.il[ps.tos] = ps.ind_level = ps.i_l_follow; + ++ps.i_l_follow; /* subsequent statements should be indented 1 */ + ps.search_brace = btype_2; + break; + + case lbrace: /* scanned { */ + break_comma = false; /* don't break comma in an initial list */ + if (ps.p_stack[ps.tos] == stmt || ps.p_stack[ps.tos] == decl + || ps.p_stack[ps.tos] == stmtl) + ++ps.i_l_follow; /* it is a random, isolated stmt group or a + * declaration */ + else { + if (s_code == e_code) { + /* + * only do this if there is nothing on the line + */ + --ps.ind_level; + /* + * it is a group as part of a while, for, etc. + */ + if (ps.p_stack[ps.tos] == swstmt && ps.case_indent >= 1) + --ps.ind_level; + /* + * for a switch, brace should be two levels out from the code + */ + } + } + + ps.p_stack[++ps.tos] = lbrace; + ps.il[ps.tos] = ps.ind_level; + ps.p_stack[++ps.tos] = stmt; + /* allow null stmt between braces */ + ps.il[ps.tos] = ps.i_l_follow; + break; + + case whilestmt: /* scanned while (...) */ + if (ps.p_stack[ps.tos] == dohead) { + /* it is matched with do stmt */ + ps.ind_level = ps.i_l_follow = ps.il[ps.tos]; + ps.p_stack[++ps.tos] = whilestmt; + ps.il[ps.tos] = ps.ind_level = ps.i_l_follow; + } + else { /* it is a while loop */ + ps.p_stack[++ps.tos] = whilestmt; + ps.il[ps.tos] = ps.i_l_follow; + ++ps.i_l_follow; + ps.search_brace = btype_2; + } + + break; + + case elselit: /* scanned an else */ + + if (ps.p_stack[ps.tos] != ifhead) + diag2(1, "Unmatched 'else'"); + else { + ps.ind_level = ps.il[ps.tos]; /* indentation for else should + * be same as for if */ + ps.i_l_follow = ps.ind_level + 1; /* everything following should + * be in 1 level */ + ps.p_stack[ps.tos] = elsehead; + /* remember if with else */ + ps.search_brace = btype_2 | ps.else_if; + } + break; + + case rbrace: /* scanned a } */ + /* stack should have or */ + if (ps.p_stack[ps.tos - 1] == lbrace) { + ps.ind_level = ps.i_l_follow = ps.il[--ps.tos]; + ps.p_stack[ps.tos] = stmt; + } + else + diag2(1, "Statement nesting error"); + break; + + case swstmt: /* had switch (...) */ + ps.p_stack[++ps.tos] = swstmt; + ps.cstk[ps.tos] = case_ind; + /* save current case indent level */ + ps.il[ps.tos] = ps.i_l_follow; + case_ind = ps.i_l_follow + ps.case_indent; /* cases should be one + * level down from + * switch */ + ps.i_l_follow += ps.case_indent + 1; /* statements should be two + * levels in */ + ps.search_brace = btype_2; + break; + + case semicolon: /* this indicates a simple stmt */ + break_comma = false; /* turn off flag to break after commas in a + * declaration */ + ps.p_stack[++ps.tos] = stmt; + ps.il[ps.tos] = ps.ind_level; + break; + + default: /* this is an error */ + diag2(1, "Unknown code to parser"); + return; + + + } /* end of switch */ + + reduce(); /* see if any reduction can be done */ + +#ifdef debug + for (i = 1; i <= ps.tos; ++i) + printf("(%d %d)", ps.p_stack[i], ps.il[i]); + printf("\n"); +#endif + + return; +} + +/* + * NAME: reduce + * + * FUNCTION: Implements the reduce part of the parsing algorithm + * + * ALGORITHM: The following reductions are done. Reductions are repeated + * until no more are possible. + * + * Old TOS New TOS + * + * + * do "dostmt" + * if "ifstmt" + * switch + * decl + * "ifelse" + * for + * while + * "dostmt" while + * + * On each reduction, ps.i_l_follow (the indentation for the following line) + * is set to the indentation level associated with the old TOS. + * + * PARAMETERS: None + * + * RETURNS: Nothing + * + * GLOBALS: ps.cstk ps.i_l_follow = ps.il ps.p_stack = ps.tos = + * + * CALLS: None + * + * CALLED BY: parse + * + * HISTORY: initial coding November 1976 D A Willcox of CAC + * + */ +/*----------------------------------------------*\ +| REDUCTION PHASE | +\*----------------------------------------------*/ +static void +reduce(void) +{ + int i; + + for (;;) { /* keep looping until there is nothing left to + * reduce */ + + switch (ps.p_stack[ps.tos]) { + + case stmt: + switch (ps.p_stack[ps.tos - 1]) { + + case stmt: + case stmtl: + /* stmtl stmt or stmt stmt */ + ps.p_stack[--ps.tos] = stmtl; + break; + + case dolit: /* */ + ps.p_stack[--ps.tos] = dohead; + ps.i_l_follow = ps.il[ps.tos]; + break; + + case ifstmt: + /* */ + ps.p_stack[--ps.tos] = ifhead; + for (i = ps.tos - 1; + ( + ps.p_stack[i] != stmt + && + ps.p_stack[i] != stmtl + && + ps.p_stack[i] != lbrace + ); + --i); + ps.i_l_follow = ps.il[i]; + /* + * for the time being, we will assume that there is no else on + * this if, and set the indentation level accordingly. If an + * else is scanned, it will be fixed up later + */ + break; + + case swstmt: + /* */ + case_ind = ps.cstk[ps.tos - 1]; + + case decl: /* finish of a declaration */ + case elsehead: + /* < else> */ + case forstmt: + /* */ + case whilestmt: + /* */ + ps.p_stack[--ps.tos] = stmt; + ps.i_l_follow = ps.il[ps.tos]; + break; + + default: /* */ + return; + + } /* end of section for on top of stack */ + break; + + case whilestmt: /* while (...) on top */ + if (ps.p_stack[ps.tos - 1] == dohead) { + /* it is termination of a do while */ + ps.tos -= 2; + break; + } + else + return; + + default: /* anything else on top */ + return; + + } + } +} diff --git a/developer_cmds/indent/pr_comment.c b/developer_cmds/indent/pr_comment.c new file mode 100644 index 0000000..ad7fe2e --- /dev/null +++ b/developer_cmds/indent/pr_comment.c @@ -0,0 +1,429 @@ +/* + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if 0 +#ifndef lint +static char sccsid[] = "@(#)pr_comment.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ +#endif + +#include +__FBSDID("$FreeBSD: src/usr.bin/indent/pr_comment.c,v 1.8 2003/06/15 09:28:17 charnier Exp $"); + +#include +#include +#include +#include "indent_globs.h" +#include "indent.h" +/* + * NAME: + * pr_comment + * + * FUNCTION: + * This routine takes care of scanning and printing comments. + * + * ALGORITHM: + * 1) Decide where the comment should be aligned, and if lines should + * be broken. + * 2) If lines should not be broken and filled, just copy up to end of + * comment. + * 3) If lines should be filled, then scan thru input_buffer copying + * characters to com_buf. Remember where the last blank, tab, or + * newline was. When line is filled, print up to last blank and + * continue copying. + * + * HISTORY: + * November 1976 D A Willcox of CAC Initial coding + * 12/6/76 D A Willcox of CAC Modification to handle + * UNIX-style comments + * + */ + +/* + * this routine processes comments. It makes an attempt to keep comments from + * going over the max line length. If a line is too long, it moves everything + * from the last blank to the next comment line. Blanks and tabs from the + * beginning of the input line are removed + */ + +void +pr_comment(void) +{ + int now_col; /* column we are in now */ + int adj_max_col; /* Adjusted max_col for when we decide to + * spill comments over the right margin */ + char *last_bl; /* points to the last blank in the output + * buffer */ + char *t_ptr; /* used for moving string */ + int unix_comment; /* tri-state variable used to decide if it is + * a unix-style comment. 0 means only blanks + * since /+*, 1 means regular style comment, 2 + * means unix style comment */ + int break_delim = comment_delimiter_on_blankline; + int l_just_saw_decl = ps.just_saw_decl; + /* + * int ps.last_nl = 0; true iff the last significant thing + * weve seen is a newline + */ + int one_liner = 1; /* true iff this comment is a one-liner */ + adj_max_col = max_col; + ps.just_saw_decl = 0; + last_bl = 0; /* no blanks found so far */ + ps.box_com = false; /* at first, assume that we are not in + * a boxed comment or some other + * comment that should not be touched */ + ++ps.out_coms; /* keep track of number of comments */ + unix_comment = 1; /* set flag to let us figure out if there is a + * unix-style comment ** DISABLED: use 0 to + * reenable this hack! */ + + /* Figure where to align and how to treat the comment */ + + if (ps.col_1 && !format_col1_comments) { /* if comment starts in column + * 1 it should not be touched */ + ps.box_com = true; + ps.com_col = 1; + } + else { + if (*buf_ptr == '-' || *buf_ptr == '*' || + (*buf_ptr == '\n' && !format_block_comments)) { + ps.box_com = true; /* A comment with a '-' or '*' immediately + * after the /+* is assumed to be a boxed + * comment. A comment with a newline + * immediately after the /+* is assumed to + * be a block comment and is treated as a + * box comment unless format_block_comments + * is nonzero (the default). */ + break_delim = 0; + } + if ( /* ps.bl_line && */ (s_lab == e_lab) && (s_code == e_code)) { + /* klg: check only if this line is blank */ + /* + * If this (*and previous lines are*) blank, dont put comment way + * out at left + */ + ps.com_col = (ps.ind_level - ps.unindent_displace) * ps.ind_size + 1; + adj_max_col = block_comment_max_col; + if (ps.com_col <= 1) + ps.com_col = 1 + !format_col1_comments; + } + else { + int target_col; + break_delim = 0; + if (s_code != e_code) + target_col = count_spaces(compute_code_target(), s_code); + else { + target_col = 1; + if (s_lab != e_lab) + target_col = count_spaces(compute_label_target(), s_lab); + } + ps.com_col = ps.decl_on_line || ps.ind_level == 0 ? ps.decl_com_ind : ps.com_ind; + if (ps.com_col < target_col) + ps.com_col = ((target_col + 7) & ~7) + 1; + if (ps.com_col + 24 > adj_max_col) + adj_max_col = ps.com_col + 24; + } + } + if (ps.box_com) { + buf_ptr[-2] = 0; + ps.n_comment_delta = 1 - count_spaces(1, in_buffer); + buf_ptr[-2] = '/'; + } + else { + ps.n_comment_delta = 0; + while (*buf_ptr == ' ' || *buf_ptr == '\t') + buf_ptr++; + } + ps.comment_delta = 0; + *e_com++ = '/'; /* put '/' followed by '*' into buffer */ + *e_com++ = '*'; + if (*buf_ptr != ' ' && !ps.box_com) + *e_com++ = ' '; + + *e_com = '\0'; + if (troff) { + now_col = 1; + adj_max_col = 80; + } + else + now_col = count_spaces(ps.com_col, s_com); /* figure what column we + * would be in if we + * printed the comment + * now */ + + /* Start to copy the comment */ + + while (1) { /* this loop will go until the comment is + * copied */ + if (*buf_ptr > 040 && *buf_ptr != '*') + ps.last_nl = 0; + CHECK_SIZE_COM; + switch (*buf_ptr) { /* this checks for various spcl cases */ + case 014: /* check for a form feed */ + if (!ps.box_com) { /* in a text comment, break the line here */ + ps.use_ff = true; + /* fix so dump_line uses a form feed */ + dump_line(); + last_bl = 0; + *e_com++ = ' '; + *e_com++ = '*'; + *e_com++ = ' '; + while (*++buf_ptr == ' ' || *buf_ptr == '\t'); + } + else { + if (++buf_ptr >= buf_end) + fill_buffer(); + *e_com++ = 014; + } + break; + + case '\n': + if (had_eof) { /* check for unexpected eof */ + printf("Unterminated comment\n"); + *e_com = '\0'; + dump_line(); + return; + } + one_liner = 0; + if (ps.box_com || ps.last_nl) { /* if this is a boxed comment, + * we dont ignore the newline */ + if (s_com == e_com) { + *e_com++ = ' '; + *e_com++ = ' '; + } + *e_com = '\0'; + if (!ps.box_com && e_com - s_com > 3) { + if (break_delim == 1 && s_com[0] == '/' + && s_com[1] == '*' && s_com[2] == ' ') { + char *t = e_com; + break_delim = 2; + e_com = s_com + 2; + *e_com = 0; + if (blanklines_before_blockcomments) + prefix_blankline_requested = 1; + dump_line(); + e_com = t; + s_com[0] = s_com[1] = s_com[2] = ' '; + } + dump_line(); + CHECK_SIZE_COM; + *e_com++ = ' '; + *e_com++ = ' '; + } + dump_line(); + now_col = ps.com_col; + } + else { + ps.last_nl = 1; + if (unix_comment != 1) { /* we not are in unix_style + * comment */ + if (unix_comment == 0 && s_code == e_code) { + /* + * if it is a UNIX-style comment, ignore the + * requirement that previous line be blank for + * unindention + */ + ps.com_col = (ps.ind_level - ps.unindent_displace) * ps.ind_size + 1; + if (ps.com_col <= 1) + ps.com_col = 2; + } + unix_comment = 2; /* permanently remember that we are in + * this type of comment */ + dump_line(); + ++line_no; + now_col = ps.com_col; + *e_com++ = ' '; + /* + * fix so that the star at the start of the line will line + * up + */ + do /* flush leading white space */ + if (++buf_ptr >= buf_end) + fill_buffer(); + while (*buf_ptr == ' ' || *buf_ptr == '\t'); + break; + } + if (*(e_com - 1) == ' ' || *(e_com - 1) == '\t') + last_bl = e_com - 1; + /* + * if there was a space at the end of the last line, remember + * where it was + */ + else { /* otherwise, insert one */ + last_bl = e_com; + CHECK_SIZE_COM; + *e_com++ = ' '; + ++now_col; + } + } + ++line_no; /* keep track of input line number */ + if (!ps.box_com) { + int nstar = 1; + do { /* flush any blanks and/or tabs at start of + * next line */ + if (++buf_ptr >= buf_end) + fill_buffer(); + if (*buf_ptr == '*' && --nstar >= 0) { + if (++buf_ptr >= buf_end) + fill_buffer(); + if (*buf_ptr == '/') + goto end_of_comment; + } + } while (*buf_ptr == ' ' || *buf_ptr == '\t'); + } + else if (++buf_ptr >= buf_end) + fill_buffer(); + break; /* end of case for newline */ + + case '*': /* must check for possibility of being at end + * of comment */ + if (++buf_ptr >= buf_end) /* get to next char after * */ + fill_buffer(); + + if (unix_comment == 0) /* set flag to show we are not in + * unix-style comment */ + unix_comment = 1; + + if (*buf_ptr == '/') { /* it is the end!!! */ + end_of_comment: + if (++buf_ptr >= buf_end) + fill_buffer(); + + if (*(e_com - 1) != ' ' && !ps.box_com) { /* insure blank before + * end */ + *e_com++ = ' '; + ++now_col; + } + if (break_delim == 1 && !one_liner && s_com[0] == '/' + && s_com[1] == '*' && s_com[2] == ' ') { + char *t = e_com; + break_delim = 2; + e_com = s_com + 2; + *e_com = 0; + if (blanklines_before_blockcomments) + prefix_blankline_requested = 1; + dump_line(); + e_com = t; + s_com[0] = s_com[1] = s_com[2] = ' '; + } + if (break_delim == 2 && e_com > s_com + 3 + /* now_col > adj_max_col - 2 && !ps.box_com */ ) { + *e_com = '\0'; + dump_line(); + now_col = ps.com_col; + } + CHECK_SIZE_COM; + *e_com++ = '*'; + *e_com++ = '/'; + *e_com = '\0'; + ps.just_saw_decl = l_just_saw_decl; + return; + } + else { /* handle isolated '*' */ + *e_com++ = '*'; + ++now_col; + } + break; + default: /* we have a random char */ + if (unix_comment == 0 && *buf_ptr != ' ' && *buf_ptr != '\t') + unix_comment = 1; /* we are not in unix-style comment */ + + *e_com = *buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + + if (*e_com == '\t') /* keep track of column */ + now_col = ((now_col - 1) & tabmask) + tabsize + 1; + else if (*e_com == '\b') /* this is a backspace */ + --now_col; + else + ++now_col; + + if (*e_com == ' ' || *e_com == '\t') + last_bl = e_com; + /* remember we saw a blank */ + + ++e_com; + if (now_col > adj_max_col && !ps.box_com && unix_comment == 1 && e_com[-1] > ' ') { + /* + * the comment is too long, it must be broken up + */ + if (break_delim == 1 && s_com[0] == '/' + && s_com[1] == '*' && s_com[2] == ' ') { + char *t = e_com; + break_delim = 2; + e_com = s_com + 2; + *e_com = 0; + if (blanklines_before_blockcomments) + prefix_blankline_requested = 1; + dump_line(); + e_com = t; + s_com[0] = s_com[1] = s_com[2] = ' '; + } + if (last_bl == 0) { /* we have seen no blanks */ + last_bl = e_com; /* fake it */ + *e_com++ = ' '; + } + *e_com = '\0'; /* print what we have */ + *last_bl = '\0'; + while (last_bl > s_com && last_bl[-1] < 040) + *--last_bl = 0; + e_com = last_bl; + dump_line(); + + *e_com++ = ' '; /* add blanks for continuation */ + *e_com++ = ' '; + *e_com++ = ' '; + + t_ptr = last_bl + 1; + last_bl = 0; + if (t_ptr >= e_com) { + while (*t_ptr == ' ' || *t_ptr == '\t') + t_ptr++; + while (*t_ptr != '\0') { /* move unprinted part of + * comment down in buffer */ + if (*t_ptr == ' ' || *t_ptr == '\t') + last_bl = e_com; + *e_com++ = *t_ptr++; + } + } + *e_com = '\0'; + now_col = count_spaces(ps.com_col, s_com); /* recompute current + * position */ + } + break; + } + } +} diff --git a/developer_cmds/lorder/lorder.1 b/developer_cmds/lorder/lorder.1 new file mode 100644 index 0000000..45fe0e6 --- /dev/null +++ b/developer_cmds/lorder/lorder.1 @@ -0,0 +1,75 @@ +.\" $NetBSD: lorder.1,v 1.6 1997/10/19 04:21:49 lukem Exp $ +.\" +.\" Copyright (c) 1990, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)lorder.1 8.2 (Berkeley) 4/28/95 +.\" +.Dd April 28, 1995 +.Dt LORDER 1 +.Os +.Sh NAME +.Nm lorder +.Nd list dependencies for object files +.Sh SYNOPSIS +.Nm +.Ar +.Sh DESCRIPTION +The +.Nm +utility uses +.Xr nm 1 +to determine interdependencies in the list of object files +specified on the command line. +.Nm +outputs a list of file names where the first file contains a symbol +which is defined by the second file. +.Pp +The output is normally used with +.Xr tsort 1 +when a library is created to determine the optimum ordering of the +object modules so that all references may be resolved in a single +pass of the loader. +.Sh EXAMPLES +.Bd -literal -offset indent +ar cr library.a `lorder ${OBJS} | tsort` +.Ed +.Sh SEE ALSO +.Xr ar 1 , +.Xr ld 1 , +.Xr nm 1 , +.Xr ranlib 1 , +.Xr tsort 1 +.Sh HISTORY +An +.Nm +utility appeared in +.At v7 . diff --git a/developer_cmds/lorder/lorder.sh b/developer_cmds/lorder/lorder.sh new file mode 100644 index 0000000..b6ed479 --- /dev/null +++ b/developer_cmds/lorder/lorder.sh @@ -0,0 +1,104 @@ +#!/bin/sh - +# $NetBSD: lorder.sh,v 1.7 1998/04/09 05:28:07 fair Exp $ +# +# Copyright (c) 1990, 1993 +# The Regents of the University of California. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. All advertising materials mentioning features or use of this software +# must display the following acknowledgement: +# This product includes software developed by the University of +# California, Berkeley and its contributors. +# 4. Neither the name of the University nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# @(#)lorder.sh 8.1 (Berkeley) 6/6/93 +# + +# If the user has set ${NM} then we use it, otherwise we use 'nm'. +# We try to find the compiler in the user's path, and if that fails we +# try to find it in the default path. If we can't find it, we punt. +# Once we find it, we canonicalize its name and set the path to the +# default path so that other commands we use are picked properly. + +if ! type "${NM:=nm}" > /dev/null 2>&1; then + PATH=/bin:/usr/bin + export PATH + if ! type "${NM}" > /dev/null 2>&1; then + echo "lorder: ${NM}: not found" + exit 1 + fi +fi +cmd='set `type "${NM}"` ; eval echo \$$#' +NM=`eval $cmd` + +# only one argument is a special case, just output the name twice +case $# in + 0) + echo "usage: lorder file ..."; + exit ;; + 1) + echo $1 $1; + exit ;; +esac + +# temporary files +R=/tmp/_reference_$$ +S=/tmp/_symbol_$$ + +# remove temporary files on HUP, INT, QUIT, PIPE, TERM +trap "rm -f $R $S; exit 1" 1 2 3 13 15 + +# if the line ends in a colon, assume it's the first occurrence of a new +# object file. Echo it twice, just to make sure it gets into the output. +# +# if the line has " T " or " D " it's a globally defined symbol, put it +# into the symbol file. +# +# if the line has " U " it's a globally undefined symbol, put it into +# the reference file. +(for file in $* ; do echo $file":" ; done ; $NM -go $*) | sed " + /:$/ { + s/:// + s/.*/& &/ + p + d + } + / [TDGR] / { + s/:.* [TDGR] / / + w $S + d + } + / U / { + s/:.* U / / + w $R + } + d +" + +# sort symbols and references on the first field (the symbol) +# join on that field, and print out the file names. +sort -k 2 $R -o $R +sort -k 2 $S -o $S +join -j 2 -o "1.1 2.1" $R $S +rm -f $R $S diff --git a/developer_cmds/rpcgen/rpc_clntout.c b/developer_cmds/rpcgen/rpc_clntout.c new file mode 100644 index 0000000..e0d2263 --- /dev/null +++ b/developer_cmds/rpcgen/rpc_clntout.c @@ -0,0 +1,230 @@ +/* $NetBSD: rpc_clntout.c,v 1.8 1997/10/18 10:53:37 lukem Exp $ */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user or with the express written consent of + * Sun Microsystems, Inc. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)rpc_clntout.c 1.11 89/02/22 (C) 1987 SMI"; +#else +__RCSID("$NetBSD: rpc_clntout.c,v 1.8 1997/10/18 10:53:37 lukem Exp $"); +#endif +#endif + +/* + * rpc_clntout.c, Client-stub outputter for the RPC protocol compiler + * Copyright (C) 1987, Sun Microsytsems, Inc. + */ +#include +#include +#include +#include "rpc_scan.h" +#include "rpc_parse.h" +#include "rpc_util.h" + +static void write_program __P((definition *)); +static char *ampr __P((char *)); +static void printbody __P((proc_list *)); + +#define DEFAULT_TIMEOUT 25 /* in seconds */ +static char RESULT[] = "clnt_res"; + + +void +write_stubs() +{ + list *l; + definition *def; + + f_print(fout, + "\n/* Default timeout can be changed using clnt_control() */\n"); + f_print(fout, "static struct timeval TIMEOUT = { %d, 0 };\n", + DEFAULT_TIMEOUT); + for (l = defined; l != NULL; l = l->next) { + def = (definition *) l->val; + if (def->def_kind == DEF_PROGRAM) { + write_program(def); + } + } +} + +static void +write_program(def) + definition *def; +{ + version_list *vp; + proc_list *proc; + + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) { + for (proc = vp->procs; proc != NULL; proc = proc->next) { + f_print(fout, "\n"); + ptype(proc->res_prefix, proc->res_type, 1); + f_print(fout, "*\n"); + pvname(proc->proc_name, vp->vers_num); + printarglist(proc, "clnt", "CLIENT *"); + f_print(fout, "{\n"); + printbody(proc); + f_print(fout, "}\n"); + } + } +} +/* Writes out declarations of procedure's argument list. + In either ANSI C style, in one of old rpcgen style (pass by reference), + or new rpcgen style (multiple arguments, pass by value); + */ + +/* sample addargname = "clnt"; sample addargtype = "CLIENT * " */ + +void +printarglist(proc, addargname, addargtype) + proc_list *proc; + char *addargname, *addargtype; +{ + + decl_list *l; + + if (!newstyle) { /* old style: always pass argument by + * reference */ + if (Cflag) { /* C++ style heading */ + f_print(fout, "("); + ptype(proc->args.decls->decl.prefix, proc->args.decls->decl.type, 1); + f_print(fout, "*argp, %s%s)\n", addargtype, addargname); + } else { + f_print(fout, "(argp, %s)\n", addargname); + f_print(fout, "\t"); + ptype(proc->args.decls->decl.prefix, proc->args.decls->decl.type, 1); + f_print(fout, "*argp;\n"); + } + } else + if (streq(proc->args.decls->decl.type, "void")) { + /* newstyle, 0 argument */ + if (Cflag) + f_print(fout, "(%s%s)\n", addargtype, addargname); + else + f_print(fout, "(%s)\n", addargname); + } else { + /* new style, 1 or multiple arguments */ + if (!Cflag) { + f_print(fout, "("); + for (l = proc->args.decls; l != NULL; l = l->next) + f_print(fout, "%s, ", l->decl.name); + f_print(fout, "%s)\n", addargname); + for (l = proc->args.decls; l != NULL; l = l->next) { + pdeclaration(proc->args.argname, &l->decl, 1, ";\n"); + } + } else {/* C++ style header */ + f_print(fout, "("); + for (l = proc->args.decls; l != NULL; l = l->next) { + pdeclaration(proc->args.argname, &l->decl, 0, ", "); + } + f_print(fout, " %s%s)\n", addargtype, addargname); + } + } + + if (!Cflag) + f_print(fout, "\t%s%s;\n", addargtype, addargname); +} + + + +static char * +ampr(type) + char *type; +{ + if (isvectordef(type, REL_ALIAS)) { + return (""); + } else { + return ("&"); + } +} + +static void +printbody(proc) + proc_list *proc; +{ + decl_list *l; + bool_t args2 = (proc->arg_num > 1); + + /* For new style with multiple arguments, need a structure in which to + * stuff the arguments. */ + if (newstyle && args2) { + f_print(fout, "\t%s", proc->args.argname); + f_print(fout, " arg;\n"); + } + f_print(fout, "\tstatic "); + if (streq(proc->res_type, "void")) { + f_print(fout, "char "); + } else { + ptype(proc->res_prefix, proc->res_type, 0); + } + f_print(fout, "%s;\n", RESULT); + f_print(fout, "\n"); + f_print(fout, "\tmemset((char *)%s%s, 0, sizeof(%s));\n", + ampr(proc->res_type), RESULT, RESULT); + if (newstyle && !args2 && (streq(proc->args.decls->decl.type, "void"))) { + /* newstyle, 0 arguments */ + f_print(fout, + "\tif (clnt_call(clnt, %s, xdr_void", proc->proc_name); + f_print(fout, + ", NULL, xdr_%s, %s%s, TIMEOUT) != RPC_SUCCESS) {\n", + stringfix(proc->res_type), ampr(proc->res_type), RESULT); + + } else + if (newstyle && args2) { + /* newstyle, multiple arguments: stuff arguments into + * structure */ + for (l = proc->args.decls; l != NULL; l = l->next) { + f_print(fout, "\targ.%s = %s;\n", + l->decl.name, l->decl.name); + } + f_print(fout, + "\tif (clnt_call(clnt, %s, xdr_%s, &arg, xdr_%s, %s%s, TIMEOUT) != RPC_SUCCESS)\n", + proc->proc_name, + proc->args.argname, + stringfix(proc->res_type), + ampr(proc->res_type), RESULT); + } else { /* single argument, new or old style */ + f_print(fout, + "\tif (clnt_call(clnt, %s, xdr_%s, %s%s, xdr_%s, %s%s, TIMEOUT) != RPC_SUCCESS)\n", + proc->proc_name, + stringfix(proc->args.decls->decl.type), + (newstyle ? "&" : ""), + (newstyle ? proc->args.decls->decl.name : "argp"), + stringfix(proc->res_type), + ampr(proc->res_type), RESULT); + } + f_print(fout, "\t\treturn (NULL);\n"); + if (streq(proc->res_type, "void")) { + f_print(fout, "\treturn ((void *)%s%s);\n", + ampr(proc->res_type), RESULT); + } else { + f_print(fout, "\treturn (%s%s);\n", ampr(proc->res_type), RESULT); + } +} diff --git a/developer_cmds/rpcgen/rpc_cout.c b/developer_cmds/rpcgen/rpc_cout.c new file mode 100644 index 0000000..ca4eb7b --- /dev/null +++ b/developer_cmds/rpcgen/rpc_cout.c @@ -0,0 +1,741 @@ +/* $NetBSD: rpc_cout.c,v 1.14 1998/08/25 20:59:40 ross Exp $ */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user or with the express written consent of + * Sun Microsystems, Inc. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)rpc_cout.c 1.13 89/02/22 (C) 1987 SMI"; +#else +__RCSID("$NetBSD: rpc_cout.c,v 1.14 1998/08/25 20:59:40 ross Exp $"); +#endif +#endif + +/* + * rpc_cout.c, XDR routine outputter for the RPC protocol compiler + */ +#include +#include +#include +#include +#include +#include "rpc_scan.h" +#include "rpc_parse.h" +#include "rpc_util.h" + +static int findtype __P((definition *, char *)); +static int undefined __P((char *)); +static void print_generic_header __P((char *, int)); +static void print_header __P((definition *)); +static void print_prog_header __P((proc_list *)); +static void print_trailer __P((void)); +static void print_ifopen __P((int, char *)); +static void print_ifarg __P((char *)); +static void print_ifsizeof __P((char *, char *)); +static void print_ifclose __P((int)); +static void print_ifstat __P((int, char *, char *, relation, char *, char *, char *)); +static void emit_enum __P((definition *)); +static void emit_program __P((definition *)); +static void emit_union __P((definition *)); +static void emit_struct __P((definition *)); +static void emit_typedef __P((definition *)); +static void print_stat __P((int, declaration *)); + +/* + * Emit the C-routine for the given definition + */ +void +emit(def) + definition *def; +{ + if (def->def_kind == DEF_CONST) { + return; + } + if (def->def_kind == DEF_PROGRAM) { + emit_program(def); + return; + } + if (def->def_kind == DEF_TYPEDEF) { + /* now we need to handle declarations like struct typedef foo + * foo; since we dont want this to be expanded into 2 calls to + * xdr_foo */ + + if (strcmp(def->def.ty.old_type, def->def_name) == 0) + return; + }; + + print_header(def); + + switch (def->def_kind) { + case DEF_UNION: + emit_union(def); + break; + case DEF_ENUM: + emit_enum(def); + break; + case DEF_STRUCT: + emit_struct(def); + break; + case DEF_TYPEDEF: + emit_typedef(def); + break; + case DEF_PROGRAM: + case DEF_CONST: + errx(1, "Internal error %s, %d: Case %d not handled\n", + __FILE__, __LINE__, def->def_kind); + break; + } + print_trailer(); +} + +static int +findtype(def, type) + definition *def; + char *type; +{ + + if (def->def_kind == DEF_PROGRAM || def->def_kind == DEF_CONST) { + return (0); + } else { + return (streq(def->def_name, type)); + } +} + +static int +undefined(type) + char *type; +{ + definition *def; + + def = (definition *) FINDVAL(defined, type, findtype); + + + return (def == NULL); +} + +static void +print_generic_header(procname, pointerp) + char *procname; + int pointerp; +{ + f_print(fout, "\n"); + f_print(fout, "bool_t\n"); + if (Cflag) { + f_print(fout, "xdr_%s(", procname); + f_print(fout, "XDR *xdrs, "); + f_print(fout, "%s ", procname); + if (pointerp) + f_print(fout, "*"); + f_print(fout, "objp)\n{\n"); + } else { + f_print(fout, "xdr_%s(xdrs, objp)\n", procname); + f_print(fout, "\tXDR *xdrs;\n"); + f_print(fout, "\t%s ", procname); + if (pointerp) + f_print(fout, "*"); + f_print(fout, "objp;\n{\n"); + } +} + +static void +print_header(def) + definition *def; +{ + print_generic_header(def->def_name, + def->def_kind != DEF_TYPEDEF || + !isvectordef(def->def.ty.old_type, def->def.ty.rel)); +} + +static void +print_prog_header(plist) + proc_list *plist; +{ + print_generic_header(plist->args.argname, 1); +} + +static void +print_trailer() +{ + f_print(fout, "\treturn (TRUE);\n"); + f_print(fout, "}\n"); +} + + +static void +print_ifopen(indent, name) + int indent; + char *name; +{ + tabify(fout, indent); + f_print(fout, "if (!xdr_%s(xdrs", name); +} + +static void +print_ifarg(arg) + char *arg; +{ + f_print(fout, ", %s", arg); +} + +static void +print_ifsizeof(prefix, type) + char *prefix; + char *type; +{ + if (streq(type, "bool")) { + f_print(fout, ", sizeof(bool_t), (xdrproc_t)xdr_bool"); + } else { + f_print(fout, ", sizeof("); + if (undefined(type) && prefix) { + f_print(fout, "%s ", prefix); + } + f_print(fout, "%s), (xdrproc_t)xdr_%s", type, type); + } +} + +static void +print_ifclose(indent) + int indent; +{ + f_print(fout, "))\n"); + tabify(fout, indent); + f_print(fout, "\treturn (FALSE);\n"); +} + +static void +print_ifstat(indent, prefix, type, rel, amax, objname, name) + int indent; + char *prefix; + char *type; + relation rel; + char *amax; + char *objname; + char *name; +{ + char *alt = NULL; + + switch (rel) { + case REL_POINTER: + print_ifopen(indent, "pointer"); + print_ifarg("(char **)"); + f_print(fout, "%s", objname); + print_ifsizeof(prefix, type); + break; + case REL_VECTOR: + if (streq(type, "string")) { + alt = "string"; + } else + if (streq(type, "opaque")) { + alt = "opaque"; + } + if (alt) { + print_ifopen(indent, alt); + print_ifarg(objname); + } else { + print_ifopen(indent, "vector"); + print_ifarg("(char *)"); + f_print(fout, "%s", objname); + } + print_ifarg(amax); + if (!alt) { + print_ifsizeof(prefix, type); + } + break; + case REL_ARRAY: + if (streq(type, "string")) { + alt = "string"; + } else + if (streq(type, "opaque")) { + alt = "bytes"; + } + if (streq(type, "string")) { + print_ifopen(indent, alt); + print_ifarg(objname); + } else { + if (alt) { + print_ifopen(indent, alt); + } else { + print_ifopen(indent, "array"); + } + print_ifarg("(char **)"); + if (*objname == '&') { + f_print(fout, "%s.%s_val, (u_int *)%s.%s_len", + objname, name, objname, name); + } else { + f_print(fout, "&%s->%s_val, (u_int *)&%s->%s_len", + objname, name, objname, name); + } + } + print_ifarg(amax); + if (!alt) { + print_ifsizeof(prefix, type); + } + break; + case REL_ALIAS: + print_ifopen(indent, type); + print_ifarg(objname); + break; + } + print_ifclose(indent); +} +/* ARGSUSED */ +static void +emit_enum(def) + definition *def; +{ + fprintf(fout, "\n"); + print_ifopen(1, "enum"); + print_ifarg("(enum_t *)objp"); + print_ifclose(1); +} + +static void +emit_program(def) + definition *def; +{ + decl_list *dl; + version_list *vlist; + proc_list *plist; + + for (vlist = def->def.pr.versions; vlist != NULL; vlist = vlist->next) + for (plist = vlist->procs; plist != NULL; plist = plist->next) { + if (!newstyle || plist->arg_num < 2) + continue; /* old style, or single + * argument */ + print_prog_header(plist); + for (dl = plist->args.decls; dl != NULL; + dl = dl->next) + print_stat(1, &dl->decl); + print_trailer(); + } +} + + +static void +emit_union(def) + definition *def; +{ + declaration *dflt; + case_list *cl; + declaration *cs; + char *object; + char *vecformat = "objp->%s_u.%s"; + char *format = "&objp->%s_u.%s"; + + f_print(fout, "\n"); + print_stat(1, &def->def.un.enum_decl); + f_print(fout, "\tswitch (objp->%s) {\n", def->def.un.enum_decl.name); + for (cl = def->def.un.cases; cl != NULL; cl = cl->next) { + f_print(fout, "\tcase %s:\n", cl->case_name); + if (cl->contflag == 1) /* a continued case statement */ + continue; + cs = &cl->case_decl; + if (!streq(cs->type, "void")) { + object = alloc(strlen(def->def_name) + strlen(format) + + strlen(cs->name) + 1); + if (isvectordef(cs->type, cs->rel)) { + s_print(object, vecformat, def->def_name, + cs->name); + } else { + s_print(object, format, def->def_name, + cs->name); + } + print_ifstat(2, cs->prefix, cs->type, cs->rel, + cs->array_max, object, cs->name); + free(object); + } + f_print(fout, "\t\tbreak;\n"); + } + dflt = def->def.un.default_decl; + f_print(fout, "\tdefault:\n"); + if (dflt != NULL) { + if (!streq(dflt->type, "void")) { + object = alloc(strlen(def->def_name) + strlen(format) + + strlen(dflt->name) + 1); + if (isvectordef(dflt->type, dflt->rel)) { + s_print(object, vecformat, def->def_name, + dflt->name); + } else { + s_print(object, format, def->def_name, + dflt->name); + } + print_ifstat(2, dflt->prefix, dflt->type, dflt->rel, + dflt->array_max, object, dflt->name); + free(object); + } + f_print(fout, "\t\tbreak;\n"); + } else { + f_print(fout, "\t\treturn (FALSE);\n"); + } + + f_print(fout, "\t}\n"); +} + +static void +emit_struct(def) + definition *def; +{ + decl_list *dl; + int i, j, size, flag; + decl_list *cur = NULL, *psav; + bas_type *ptr; + char *sizestr, *plus; + char ptemp[256]; + int can_inline; + + + if (doinline == 0) { + fprintf(fout, "\n"); + for (dl = def->def.st.decls; dl != NULL; dl = dl->next) + print_stat(1, &dl->decl); + return; + } + size = 0; + can_inline = 0; + for (dl = def->def.st.decls; dl != NULL; dl = dl->next) + if ((dl->decl.prefix == NULL) && + ((ptr = find_type(dl->decl.type)) != NULL) && + ((dl->decl.rel == REL_ALIAS) || (dl->decl.rel == REL_VECTOR))) { + + if (dl->decl.rel == REL_ALIAS) + size += ptr->length; + else { + can_inline = 1; + break; /* can be inlined */ + }; + } else { + if (size >= doinline) { + can_inline = 1; + break; /* can be inlined */ + } + size = 0; + } + if (size > doinline) + can_inline = 1; + + if (can_inline == 0) { /* can not inline, drop back to old mode */ + fprintf(fout, "\n"); + for (dl = def->def.st.decls; dl != NULL; dl = dl->next) + print_stat(1, &dl->decl); + return; + }; + + /* May cause lint to complain. but ... */ + f_print(fout, "\tint32_t *buf;\n"); + + flag = PUT; + f_print(fout, "\n\tif (xdrs->x_op == XDR_ENCODE) {\n"); + + for (j = 0; j < 2; j++) { + i = 0; + size = 0; + sizestr = NULL; + for (dl = def->def.st.decls; dl != NULL; dl = dl->next) { /* xxx */ + + /* now walk down the list and check for basic types */ + if ((dl->decl.prefix == NULL) && ((ptr = find_type(dl->decl.type)) != NULL) && ((dl->decl.rel == REL_ALIAS) || (dl->decl.rel == REL_VECTOR))) { + if (i == 0) + cur = dl; + i++; + + if (dl->decl.rel == REL_ALIAS) + size += ptr->length; + else { + /* this is required to handle arrays */ + + if (sizestr == NULL) + plus = ""; + else + plus = " + "; + + if (ptr->length != 1) + s_print(ptemp, "%s%s * %d", plus, dl->decl.array_max, ptr->length); + else + s_print(ptemp, "%s%s", plus, dl->decl.array_max); + + /* now concatenate to sizestr !!!! */ + if (sizestr == NULL) + sizestr = strdup(ptemp); + else { + sizestr = (char *) realloc(sizestr, strlen(sizestr) + strlen(ptemp) + 1); + if (sizestr == NULL) { + + f_print(stderr, "Fatal error : no memory\n"); + crash(); + }; + sizestr = strcat(sizestr, ptemp); /* build up length of + * array */ + + } + } + + } else { + if (i > 0) { + if (sizestr == NULL && size < doinline) { + /* don't expand into inline + * code if size < doinline */ + while (cur != dl) { + print_stat(2, &cur->decl); + cur = cur->next; + } + } else { + + + + /* were already looking at a + * xdr_inlineable structure */ + if (sizestr == NULL) + f_print(fout, "\t\tbuf = (int32_t *)XDR_INLINE(xdrs, %d * BYTES_PER_XDR_UNIT);\n", + size); + else + if (size == 0) + f_print(fout, + "\t\tbuf = (int32_t *)XDR_INLINE(xdrs, %s * BYTES_PER_XDR_UNIT);\n", + sizestr); + else + f_print(fout, + "\t\tbuf = (int32_t *)XDR_INLINE(xdrs, (%d + %s) * BYTES_PER_XDR_UNIT);\n", + size, sizestr); + + f_print(fout, "\t\tif (buf == NULL) {\n"); + + psav = cur; + while (cur != dl) { + print_stat(3, &cur->decl); + cur = cur->next; + } + + f_print(fout, "\t\t} else {\n"); + + cur = psav; + while (cur != dl) { + emit_inline(&cur->decl, flag); + cur = cur->next; + } + + f_print(fout, "\t\t}\n"); + } + } + size = 0; + i = 0; + sizestr = NULL; + print_stat(2, &dl->decl); + } + + } + if (i > 0) { + if (sizestr == NULL && size < doinline) { + /* don't expand into inline code if size < + * doinline */ + while (cur != dl) { + print_stat(2, &cur->decl); + cur = cur->next; + } + } else { + + /* were already looking at a xdr_inlineable + * structure */ + if (sizestr == NULL) + f_print(fout, "\t\tbuf = (int32_t *)XDR_INLINE(xdrs, %d * BYTES_PER_XDR_UNIT);\n", + size); + else + if (size == 0) + f_print(fout, + "\t\tbuf = (int32_t *)XDR_INLINE(xdrs, %s * BYTES_PER_XDR_UNIT);\n", + sizestr); + else + f_print(fout, + "\t\tbuf = (int32_t *)XDR_INLINE(xdrs, (%d + %s) * BYTES_PER_XDR_UNIT);\n", + size, sizestr); + + f_print(fout, "\t\tif (buf == NULL) {\n"); + + psav = cur; + while (cur != NULL) { + print_stat(3, &cur->decl); + cur = cur->next; + } + f_print(fout, "\t\t} else {\n"); + + cur = psav; + while (cur != dl) { + emit_inline(&cur->decl, flag); + cur = cur->next; + } + + f_print(fout, "\t\t}\n"); + + } + } + if (flag == PUT) { + flag = GET; + f_print(fout, "\t} else if (xdrs->x_op == XDR_DECODE) {\n"); + } + } + + f_print(fout, "\t} else {\n"); + + /* now take care of XDR_FREE case */ + + for (dl = def->def.st.decls; dl != NULL; dl = dl->next) + print_stat(2, &dl->decl); + + f_print(fout, "\t}\n"); +} + +static void +emit_typedef(def) + definition *def; +{ + char *prefix = def->def.ty.old_prefix; + char *type = def->def.ty.old_type; + char *amax = def->def.ty.array_max; + relation rel = def->def.ty.rel; + + fprintf(fout, "\n"); + print_ifstat(1, prefix, type, rel, amax, "objp", def->def_name); +} + +static void +print_stat(indent, dec) + declaration *dec; + int indent; +{ + char *prefix = dec->prefix; + char *type = dec->type; + char *amax = dec->array_max; + relation rel = dec->rel; + char name[256]; + + if (isvectordef(type, rel)) { + s_print(name, "objp->%s", dec->name); + } else { + s_print(name, "&objp->%s", dec->name); + } + print_ifstat(indent, prefix, type, rel, amax, name, dec->name); +} + + +void +emit_inline(decl, flag) + declaration *decl; + int flag; +{ + +/*check whether an array or not */ + + switch (decl->rel) { + case REL_ALIAS: + emit_single_in_line(decl, flag, REL_ALIAS); + break; + case REL_VECTOR: + f_print(fout, "\t\t\t{\n"); + f_print(fout, "\t\t\t\tint i;\n"); + f_print(fout, "\t\t\t\t%s *genp;\n", decl->type); + f_print(fout, "\n"); + f_print(fout, "\t\t\t\tfor (i = 0, genp = objp->%s;\n", + decl->name); + f_print(fout, "\t\t\t\t i < %s; i++) {\n\t\t", + decl->array_max); + emit_single_in_line(decl, flag, REL_VECTOR); + f_print(fout, "\t\t\t\t}\n\t\t\t}\n"); + break; + case REL_ARRAY: + case REL_POINTER: + errx(1, "Internal error %s, %d: Case %d not handled\n", + __FILE__, __LINE__, decl->rel); + } +} + +void +emit_single_in_line(decl, flag, rel) + declaration *decl; + int flag; + relation rel; +{ + char *upp_case; + int freed = 0; + + if (flag == PUT) + f_print(fout, "\t\t\tIXDR_PUT_"); + else + if (rel == REL_ALIAS) + f_print(fout, "\t\t\tobjp->%s = IXDR_GET_", decl->name); + else + f_print(fout, "\t\t\t*genp++ = IXDR_GET_"); + + upp_case = upcase(decl->type); + + /* hack - XX */ + if (strcmp(upp_case, "INT") == 0) { + free(upp_case); + freed = 1; + upp_case = "LONG"; + } + if (strcmp(upp_case, "U_INT") == 0) { + free(upp_case); + freed = 1; + upp_case = "U_LONG"; + } + if (flag == PUT) + if (rel == REL_ALIAS) + f_print(fout, "%s(buf, objp->%s);\n", upp_case, decl->name); + else + f_print(fout, "%s(buf, *genp++);\n", upp_case); + + else + f_print(fout, "%s(buf);\n", upp_case); + if (!freed) + free(upp_case); + +} + + +char * +upcase(str) + char *str; +{ + char *ptr, *hptr; + + + ptr = (char *) malloc(strlen(str) + 1); + if (ptr == (char *) NULL) { + f_print(stderr, "malloc failed\n"); + exit(1); + }; + + hptr = ptr; + while (*str != '\0') + *ptr++ = toupper(*str++); + + *ptr = '\0'; + return (hptr); + +} diff --git a/developer_cmds/rpcgen/rpc_hout.c b/developer_cmds/rpcgen/rpc_hout.c new file mode 100644 index 0000000..3b8811f --- /dev/null +++ b/developer_cmds/rpcgen/rpc_hout.c @@ -0,0 +1,534 @@ +/* $NetBSD: rpc_hout.c,v 1.9 1998/02/11 23:11:17 lukem Exp $ */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user or with the express written consent of + * Sun Microsystems, Inc. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)rpc_hout.c 1.12 89/02/22 (C) 1987 SMI"; +#else +__RCSID("$NetBSD: rpc_hout.c,v 1.9 1998/02/11 23:11:17 lukem Exp $"); +#endif +#endif + +/* + * rpc_hout.c, Header file outputter for the RPC protocol compiler + */ +#include +#include +#include +#include "rpc_scan.h" +#include "rpc_parse.h" +#include "rpc_util.h" + +static void pconstdef __P((definition *)); +static void pargdef __P((definition *)); +static void pstructdef __P((definition *)); +static void puniondef __P((definition *)); +static void pdefine __P((char *, char *)); +static void puldefine __P((char *, char *)); +static int define_printed __P((proc_list *, version_list *)); +static void pprogramdef __P((definition *)); +static void parglist __P((proc_list *, char *)); +static void penumdef __P((definition *)); +static void ptypedef __P((definition *)); +static int undefined2 __P((char *, char *)); + +/* + * Print the C-version of an xdr definition + */ +void +print_datadef(def) + definition *def; +{ + + if (def->def_kind == DEF_PROGRAM) /* handle data only */ + return; + + if (def->def_kind != DEF_CONST) { + f_print(fout, "\n"); + } + switch (def->def_kind) { + case DEF_STRUCT: + pstructdef(def); + break; + case DEF_UNION: + puniondef(def); + break; + case DEF_ENUM: + penumdef(def); + break; + case DEF_TYPEDEF: + ptypedef(def); + break; + case DEF_PROGRAM: + pprogramdef(def); + break; + case DEF_CONST: + pconstdef(def); + break; + } + if (def->def_kind != DEF_PROGRAM && def->def_kind != DEF_CONST) { + pxdrfuncdecl(def->def_name, + def->def_kind != DEF_TYPEDEF || + !isvectordef(def->def.ty.old_type, def->def.ty.rel)); + + } +} + + +void +print_funcdef(def) + definition *def; +{ + switch (def->def_kind) { + case DEF_PROGRAM: + f_print(fout, "\n"); + pprogramdef(def); + break; + case DEF_CONST: + case DEF_TYPEDEF: + case DEF_ENUM: + case DEF_UNION: + case DEF_STRUCT: + break; + } +} + +void +pxdrfuncdecl(name, pointerp) + char *name; + int pointerp; +{ + + f_print(fout, "#ifdef __cplusplus\n"); + f_print(fout, "extern \"C\" bool_t xdr_%s(XDR *, %s%s);\n", + name, + name, pointerp ? ("*") : ""); + f_print(fout, "#elif __STDC__\n"); + f_print(fout, "extern bool_t xdr_%s(XDR *, %s%s);\n", + name, + name, pointerp ? ("*") : ""); + f_print(fout, "#else /* Old Style C */\n"); + f_print(fout, "bool_t xdr_%s();\n", name); + f_print(fout, "#endif /* Old Style C */\n\n"); +} + + +static void +pconstdef(def) + definition *def; +{ + pdefine(def->def_name, def->def.co); +} +/* print out the definitions for the arguments of functions in the + header file +*/ +static void +pargdef(def) + definition *def; +{ + decl_list *l; + version_list *vers; + char *name; + proc_list *plist; + + + for (vers = def->def.pr.versions; vers != NULL; vers = vers->next) { + for (plist = vers->procs; plist != NULL; + plist = plist->next) { + + if (!newstyle || plist->arg_num < 2) { + continue; /* old style or single args */ + } + name = plist->args.argname; + f_print(fout, "struct %s {\n", name); + for (l = plist->args.decls; + l != NULL; l = l->next) { + pdeclaration(name, &l->decl, 1, ";\n"); + } + f_print(fout, "};\n"); + f_print(fout, "typedef struct %s %s;\n", name, name); + pxdrfuncdecl(name, 0); + f_print(fout, "\n"); + } + } + +} + + +static void +pstructdef(def) + definition *def; +{ + decl_list *l; + char *name = def->def_name; + + f_print(fout, "struct %s {\n", name); + for (l = def->def.st.decls; l != NULL; l = l->next) { + pdeclaration(name, &l->decl, 1, ";\n"); + } + f_print(fout, "};\n"); + f_print(fout, "typedef struct %s %s;\n", name, name); +} + +static void +puniondef(def) + definition *def; +{ + case_list *l; + char *name = def->def_name; + declaration *decl; + + f_print(fout, "struct %s {\n", name); + decl = &def->def.un.enum_decl; + if (streq(decl->type, "bool")) { + f_print(fout, "\tbool_t %s;\n", decl->name); + } else { + f_print(fout, "\t%s %s;\n", decl->type, decl->name); + } + f_print(fout, "\tunion {\n"); + for (l = def->def.un.cases; l != NULL; l = l->next) { + if (l->contflag == 0) + pdeclaration(name, &l->case_decl, 2, ";\n"); + } + decl = def->def.un.default_decl; + if (decl && !streq(decl->type, "void")) { + pdeclaration(name, decl, 2, ";\n"); + } + f_print(fout, "\t} %s_u;\n", name); + f_print(fout, "};\n"); + f_print(fout, "typedef struct %s %s;\n", name, name); +} + +static void +pdefine(name, num) + char *name; + char *num; +{ + f_print(fout, "#define %s %s\n", name, num); +} + +static void +puldefine(name, num) + char *name; + char *num; +{ + f_print(fout, "#define %s ((rpc_uint)%s)\n", name, num); +} + +static int +define_printed(stop, start) + proc_list *stop; + version_list *start; +{ + version_list *vers; + proc_list *proc; + + for (vers = start; vers != NULL; vers = vers->next) { + for (proc = vers->procs; proc != NULL; proc = proc->next) { + if (proc == stop) { + return (0); + } else + if (streq(proc->proc_name, stop->proc_name)) { + return (1); + } + } + } + errx(1, "Internal error %s, %d: procedure not found\n", + __FILE__, __LINE__); + /* NOTREACHED */ +} + +static void +pprogramdef(def) + definition *def; +{ + version_list *vers; + proc_list *proc; + int i; + char *ext; + + pargdef(def); + + puldefine(def->def_name, def->def.pr.prog_num); + for (vers = def->def.pr.versions; vers != NULL; vers = vers->next) { + if (tblflag) { + f_print(fout, "extern struct rpcgen_table %s_%s_table[];\n", + locase(def->def_name), vers->vers_num); + f_print(fout, "extern %s_%s_nproc;\n", + locase(def->def_name), vers->vers_num); + } + puldefine(vers->vers_name, vers->vers_num); + + /* Print out 3 definitions, one for ANSI-C, another for C++, a + * third for old style C */ + + for (i = 0; i < 3; i++) { + if (i == 0) { + f_print(fout, "\n#ifdef __cplusplus\n"); + ext = "extern \"C\" "; + } else + if (i == 1) { + f_print(fout, "\n#elif __STDC__\n"); + ext = "extern "; + } else { + f_print(fout, "\n#else /* Old Style C */\n"); + ext = "extern "; + } + + + for (proc = vers->procs; proc != NULL; proc = proc->next) { + if (!define_printed(proc, def->def.pr.versions)) { + puldefine(proc->proc_name, proc->proc_num); + } + f_print(fout, "%s", ext); + pprocdef(proc, vers, "CLIENT *", 0, i); + f_print(fout, "%s", ext); + pprocdef(proc, vers, "struct svc_req *", 1, i); + + } + + } + f_print(fout, "#endif /* Old Style C */\n"); + } +} + +void +pprocdef(proc, vp, addargtype, server_p, mode) + proc_list *proc; + version_list *vp; + char *addargtype; + int server_p; + int mode; +{ + + ptype(proc->res_prefix, proc->res_type, 1); + f_print(fout, "* "); + if (server_p) + pvname_svc(proc->proc_name, vp->vers_num); + else + pvname(proc->proc_name, vp->vers_num); + + /* + * mode 0 == cplusplus, mode 1 = ANSI-C, mode 2 = old style C + */ + if (mode == 0 || mode == 1) + parglist(proc, addargtype); + else + f_print(fout, "();\n"); +} + + +/* print out argument list of procedure */ +static void +parglist(proc, addargtype) + proc_list *proc; + char *addargtype; +{ + decl_list *dl; + + f_print(fout, "("); + + if (proc->arg_num < 2 && newstyle && + streq(proc->args.decls->decl.type, "void")) { + /* 0 argument in new style: do nothing */ + } else { + for (dl = proc->args.decls; dl != NULL; dl = dl->next) { + ptype(dl->decl.prefix, dl->decl.type, 1); + if (!newstyle) + f_print(fout, "*"); /* old style passes by + * reference */ + + f_print(fout, ", "); + } + } + + f_print(fout, "%s);\n", addargtype); +} + +static void +penumdef(def) + definition *def; +{ + char *name = def->def_name; + enumval_list *l; + char *last = NULL; + int count = 0; + + f_print(fout, "enum %s {\n", name); + for (l = def->def.en.vals; l != NULL; l = l->next) { + f_print(fout, "\t%s", l->name); + if (l->assignment) { + f_print(fout, " = %s", l->assignment); + last = l->assignment; + count = 1; + } else { + if (last == NULL) { + f_print(fout, " = %d", count++); + } else { + f_print(fout, " = %s + %d", last, count++); + } + } + f_print(fout, ",\n"); + } + f_print(fout, "};\n"); + f_print(fout, "typedef enum %s %s;\n", name, name); +} + +static void +ptypedef(def) + definition *def; +{ + char *name = def->def_name; + char *old = def->def.ty.old_type; + char prefix[8]; /* enough to contain "struct ", including NUL */ + relation rel = def->def.ty.rel; + + + if (!streq(name, old)) { + if (streq(old, "string")) { + old = "char"; + rel = REL_POINTER; + } else + if (streq(old, "opaque")) { + old = "char"; + } else + if (streq(old, "bool")) { + old = "bool_t"; + } + if (undefined2(old, name) && def->def.ty.old_prefix) { + s_print(prefix, "%s ", def->def.ty.old_prefix); + } else { + prefix[0] = 0; + } + f_print(fout, "typedef "); + switch (rel) { + case REL_ARRAY: + f_print(fout, "struct {\n"); + f_print(fout, "\tu_int %s_len;\n", name); + f_print(fout, "\t%s%s *%s_val;\n", prefix, old, name); + f_print(fout, "} %s", name); + break; + case REL_POINTER: + f_print(fout, "%s%s *%s", prefix, old, name); + break; + case REL_VECTOR: + f_print(fout, "%s%s %s[%s]", prefix, old, name, + def->def.ty.array_max); + break; + case REL_ALIAS: + f_print(fout, "%s%s %s", prefix, old, name); + break; + } + f_print(fout, ";\n"); + } +} + +void +pdeclaration(name, dec, tab, separator) + char *name; + declaration *dec; + int tab; + char *separator; +{ + char buf[8]; /* enough to hold "struct ", include NUL */ + char *prefix; + char *type; + + if (streq(dec->type, "void")) { + return; + } + tabify(fout, tab); + if (streq(dec->type, name) && !dec->prefix) { + f_print(fout, "struct "); + } + if (streq(dec->type, "string")) { + f_print(fout, "char *%s", dec->name); + } else { + prefix = ""; + if (streq(dec->type, "bool")) { + type = "bool_t"; + } else + if (streq(dec->type, "opaque")) { + type = "char"; + } else { + if (dec->prefix) { + s_print(buf, "%s ", dec->prefix); + prefix = buf; + } + type = dec->type; + } + switch (dec->rel) { + case REL_ALIAS: + f_print(fout, "%s%s %s", prefix, type, dec->name); + break; + case REL_VECTOR: + f_print(fout, "%s%s %s[%s]", prefix, type, dec->name, + dec->array_max); + break; + case REL_POINTER: + f_print(fout, "%s%s *%s", prefix, type, dec->name); + break; + case REL_ARRAY: + f_print(fout, "struct {\n"); + tabify(fout, tab); + f_print(fout, "\tu_int %s_len;\n", dec->name); + tabify(fout, tab); + f_print(fout, "\t%s%s *%s_val;\n", prefix, type, dec->name); + tabify(fout, tab); + f_print(fout, "} %s", dec->name); + break; + } + } + f_print(fout, "%s", separator); +} + +static int +undefined2(type, stop) + char *type; + char *stop; +{ + list *l; + definition *def; + + for (l = defined; l != NULL; l = l->next) { + def = (definition *) l->val; + if (def->def_kind != DEF_PROGRAM) { + if (streq(def->def_name, stop)) { + return (1); + } else + if (streq(def->def_name, type)) { + return (0); + } + } + } + return (1); +} diff --git a/developer_cmds/rpcgen/rpc_main.c b/developer_cmds/rpcgen/rpc_main.c new file mode 100644 index 0000000..a7a15a8 --- /dev/null +++ b/developer_cmds/rpcgen/rpc_main.c @@ -0,0 +1,1170 @@ +/* $NetBSD: rpc_main.c,v 1.14 1997/10/18 10:53:53 lukem Exp $ */ + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user or with the express written consent of + * Sun Microsystems, Inc. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)rpc_main.c 1.30 89/03/30 (C) 1987 SMI"; +#else +__RCSID("$NetBSD: rpc_main.c,v 1.14 1997/10/18 10:53:53 lukem Exp $"); +#endif +#endif + +/* + * rpc_main.c, Top level of the RPC protocol compiler. + */ + +#define RPCGEN_VERSION "199506"/* This program's version (year & month) */ + +#include +#include +#include +#include +#include +#include +#ifdef __TURBOC__ +#define MAXPATHLEN 80 +#include +#include +#else +#include +#include +#include +#endif +#include +#include "rpc_scan.h" +#include "rpc_parse.h" +#include "rpc_util.h" + +#define EXTEND 1 /* alias for TRUE */ +#define DONT_EXTEND 0 /* alias for FALSE */ + +#define SVR4_CPP "/usr/ccs/lib/cpp" +#define SUNOS_CPP "/lib/cpp" +static int cppDefined = 0; /* explicit path for C preprocessor */ + +struct commandline { + int cflag; /* xdr C routines */ + int hflag; /* header file */ + int lflag; /* client side stubs */ + int mflag; /* server side stubs */ + int nflag; /* netid flag */ + int sflag; /* server stubs for the given transport */ + int tflag; /* dispatch Table file */ + int Ssflag; /* produce server sample code */ + int Scflag; /* produce client sample code */ + char *infile; /* input module name */ + char *outfile; /* output module name */ +}; + + +static char *cmdname; + +static char *svcclosetime = "120"; +static char *CPP = "/usr/bin/cpp"; +static char CPPFLAGS[] = "-C"; +static char pathbuf[MAXPATHLEN + 1]; +static char *allv[] = { + "rpcgen", "-s", "udp", "-s", "tcp", +}; +static int allc = sizeof(allv) / sizeof(allv[0]); +static char *allnv[] = { + "rpcgen", "-s", "netpath", +}; +static int allnc = sizeof(allnv) / sizeof(allnv[0]); + +#define ARGLISTLEN 20 +#define FIXEDARGS 2 + +static char *arglist[ARGLISTLEN]; +static int argcount = FIXEDARGS; + + +int nonfatalerrors; /* errors */ +int inetdflag /* = 1 */ ; /* Support for inetd *//* is now the default */ +int pmflag; /* Support for port monitors */ +int logflag; /* Use syslog instead of fprintf for errors */ +int tblflag; /* Support for dispatch table file */ +int callerflag; /* Generate svc_caller() function */ + +#define INLINE 3 +/*length at which to start doing an inline */ + +int doinline = INLINE; /* length at which to start doing an inline. 3 + * = default if 0, no xdr_inline code */ + +int indefinitewait; /* If started by port monitors, hang till it + * wants */ +int exitnow; /* If started by port monitors, exit after the + * call */ +int timerflag; /* TRUE if !indefinite && !exitnow */ +int newstyle; /* newstyle of passing arguments (by value) */ +int Cflag = 0; /* ANSI C syntax */ +static int allfiles; /* generate all files */ +int tirpcflag = 0; /* generating code for tirpc, by default */ + +#ifdef __MSDOS__ +static char *dos_cppfile = NULL; +#endif + +int main __P((int, char *[])); + +static char *extendfile __P((char *, char *)); +static void open_output __P((char *, char *)); +static void add_warning __P((void)); +static void clear_args __P((void)); +static void find_cpp __P((void)); +static void open_input __P((char *, char *)); +static int check_nettype __P((char *, char *[])); +static void c_output __P((char *, char *, int, char *)); +static void c_initialize __P((void)); +static char *generate_guard __P((char *)); +static void h_output __P((char *, char *, int, char *)); +static void s_output __P((int, char *[], char *, char *, int, char *, int, int)); +static void l_output __P((char *, char *, int, char *)); +static void t_output __P((char *, char *, int, char *)); +static void svc_output __P((char *, char *, int, char *)); +static void clnt_output __P((char *, char *, int, char *)); +static int do_registers __P((int, char *[])); +static void addarg __P((char *)); +static void putarg __P((int, char *)); +static void checkfiles __P((char *, char *)); +static int parseargs __P((int, char *[], struct commandline *)); +static void usage __P((void)); +static void options_usage __P((void)); + +pid_t childpid; + +int +main(argc, argv) + int argc; + char *argv[]; +{ + struct commandline cmd; + + (void) memset((char *) &cmd, 0, sizeof(struct commandline)); + clear_args(); + if (!parseargs(argc, argv, &cmd)) + usage(); + + if (cmd.cflag || cmd.hflag || cmd.lflag || cmd.tflag || cmd.sflag || + cmd.mflag || cmd.nflag || cmd.Ssflag || cmd.Scflag) { + checkfiles(cmd.infile, cmd.outfile); + } else + checkfiles(cmd.infile, NULL); + + if (cmd.cflag) { + c_output(cmd.infile, "-DRPC_XDR", DONT_EXTEND, cmd.outfile); + } else + if (cmd.hflag) { + h_output(cmd.infile, "-DRPC_HDR", DONT_EXTEND, cmd.outfile); + } else + if (cmd.lflag) { + l_output(cmd.infile, "-DRPC_CLNT", DONT_EXTEND, cmd.outfile); + } else + if (cmd.sflag || cmd.mflag || (cmd.nflag)) { + s_output(argc, argv, cmd.infile, "-DRPC_SVC", DONT_EXTEND, + cmd.outfile, cmd.mflag, cmd.nflag); + } else + if (cmd.tflag) { + t_output(cmd.infile, "-DRPC_TBL", DONT_EXTEND, cmd.outfile); + } else + if (cmd.Ssflag) { + svc_output(cmd.infile, "-DRPC_SERVER", DONT_EXTEND, cmd.outfile); + } else + if (cmd.Scflag) { + clnt_output(cmd.infile, "-DRPC_CLIENT", DONT_EXTEND, cmd.outfile); + } else { + /* the rescans + * are + * required, + * since cpp + * may effect + * input */ + c_output(cmd.infile, "-DRPC_XDR", EXTEND, "_xdr.c"); + reinitialize(); + h_output(cmd.infile, "-DRPC_HDR", EXTEND, ".h"); + reinitialize(); + l_output(cmd.infile, "-DRPC_CLNT", EXTEND, "_clnt.c"); + reinitialize(); + if (inetdflag || !tirpcflag) + s_output(allc, allv, cmd.infile, "-DRPC_SVC", EXTEND, + "_svc.c", cmd.mflag, cmd.nflag); + else + s_output(allnc, allnv, cmd.infile, "-DRPC_SVC", + EXTEND, "_svc.c", cmd.mflag, cmd.nflag); + if (tblflag) { + reinitialize(); + t_output(cmd.infile, "-DRPC_TBL", EXTEND, "_tbl.i"); + } + if (allfiles) { + reinitialize(); + svc_output(cmd.infile, "-DRPC_SERVER", EXTEND, "_server.c"); + } + if (allfiles) { + reinitialize(); + clnt_output(cmd.infile, "-DRPC_CLIENT", EXTEND, "_client.c"); + } + } +#ifdef __MSDOS__ + if (dos_cppfile != NULL) { + (void) fclose(fin); + (void) unlink(dos_cppfile); + } +#endif + exit(nonfatalerrors); + /* NOTREACHED */ +} +/* + * add extension to filename + */ +static char * +extendfile(path, ext) + char *path; + char *ext; +{ + char *file; + char *res; + char *p; + + if ((file = strrchr(path, '/')) == NULL) + file = path; + else + file++; + + res = alloc(strlen(file) + strlen(ext) + 1); + if (res == NULL) { + errx(1, "Out of memory"); + } + p = strrchr(file, '.'); + if (p == NULL) { + p = file + strlen(file); + } + (void) strcpy(res, file); + (void) strcpy(res + (p - file), ext); + return (res); +} +/* + * Open output file with given extension + */ +static void +open_output(infile, outfile) + char *infile; + char *outfile; +{ + + if (outfile == NULL) { + fout = stdout; + return; + } + if (infile != NULL && streq(outfile, infile)) { + f_print(stderr, "%s: output would overwrite %s\n", cmdname, + infile); + crash(); + } + fout = fopen(outfile, "w"); + if (fout == NULL) { + f_print(stderr, "%s: unable to open ", cmdname); + perror(outfile); + crash(); + } + record_open(outfile); + +} + +static void +add_warning() +{ + f_print(fout, "/*\n"); + f_print(fout, " * Please do not edit this file.\n"); + f_print(fout, " * It was generated using rpcgen.\n"); + f_print(fout, " */\n\n"); +} +/* clear list of arguments */ +static void +clear_args() +{ + int i; + for (i = FIXEDARGS; i < ARGLISTLEN; i++) + arglist[i] = NULL; + argcount = FIXEDARGS; +} +/* make sure that a CPP exists */ +static void +find_cpp() +{ + struct stat buf; + + if (stat(CPP, &buf) < 0) { /* SVR4 or explicit cpp does not exist */ + if (cppDefined) { + fprintf(stderr, "cannot find C preprocessor: %s\n", CPP); + crash(); + } else { /* try the other one */ + CPP = SUNOS_CPP; + if (stat(CPP, &buf) < 0) { /* can't find any cpp */ + fprintf(stderr, "cannot find any C preprocessor (cpp)\n"); + crash(); + } + } + } +} +/* + * Open input file with given define for C-preprocessor + */ +static void +open_input(infile, define) + char *infile; + char *define; +{ + int pd[2]; + + infilename = (infile == NULL) ? "" : infile; +#ifdef __MSDOS__ +#define DOSCPP "\\prog\\bc31\\bin\\cpp.exe" + { + int retval; + char drive[MAXDRIVE], dir[MAXDIR], name[MAXFILE], ext[MAXEXT]; + char cppfile[MAXPATH]; + char *cpp; + + if ((cpp = searchpath("cpp.exe")) == NULL + && (cpp = getenv("RPCGENCPP")) == NULL) + cpp = DOSCPP; + + putarg(0, cpp); + putarg(1, "-P-"); + putarg(2, CPPFLAGS); + addarg(define); + addarg(infile); + addarg(NULL); + + retval = spawnvp(P_WAIT, arglist[0], arglist); + if (retval != 0) { + fprintf(stderr, "%s: C PreProcessor failed\n", cmdname); + crash(); + } + fnsplit(infile, drive, dir, name, ext); + fnmerge(cppfile, drive, dir, name, ".i"); + + fin = fopen(cppfile, "r"); + if (fin == NULL) { + f_print(stderr, "%s: ", cmdname); + perror(cppfile); + crash(); + } + dos_cppfile = strdup(cppfile); + if (dos_cppfile == NULL) { + fprintf(stderr, "%s: out of memory\n", cmdname); + crash(); + } + } +#else + (void) pipe(pd); + switch (childpid = fork()) { + case 0: + find_cpp(); + putarg(0, CPP); + putarg(1, CPPFLAGS); + addarg(define); + addarg(infile); + addarg((char *) NULL); + (void) close(1); + (void) dup2(pd[1], 1); + (void) close(pd[0]); + execv(arglist[0], arglist); + perror("execv"); + exit(1); + case -1: + perror("fork"); + exit(1); + } + (void) close(pd[1]); + fin = fdopen(pd[0], "r"); +#endif + if (fin == NULL) { + f_print(stderr, "%s: ", cmdname); + perror(infilename); + crash(); + } +} +/* valid tirpc nettypes */ +static char *valid_ti_nettypes[] = +{ + "netpath", + "visible", + "circuit_v", + "datagram_v", + "circuit_n", + "datagram_n", + "udp", + "tcp", + "raw", + NULL +}; +/* valid inetd nettypes */ +static char *valid_i_nettypes[] = +{ + "udp", + "tcp", + NULL +}; + +static int +check_nettype(name, list_to_check) + char *name; + char *list_to_check[]; +{ + int i; + for (i = 0; list_to_check[i] != NULL; i++) { + if (strcmp(name, list_to_check[i]) == 0) { + return 1; + } + } + f_print(stderr, "illegal nettype :\'%s\'\n", name); + return 0; +} +/* + * Compile into an XDR routine output file + */ + +static void +c_output(infile, define, extend, outfile) + char *infile; + char *define; + int extend; + char *outfile; +{ + definition *def; + char *include; + char *outfilename; + long tell; + + c_initialize(); + open_input(infile, define); + outfilename = extend ? extendfile(infile, outfile) : outfile; + open_output(infile, outfilename); + add_warning(); + if (infile && (include = extendfile(infile, ".h"))) { + f_print(fout, "#include \"%s\"\n", include); + free(include); + /* .h file already contains rpc/rpc.h */ + } else + f_print(fout, "#include \n"); + tell = ftell(fout); + while ((def = get_definition()) != NULL) { + emit(def); + } + if (extend && tell == ftell(fout)) { + (void) unlink(outfilename); + } +} + + +static void +c_initialize() +{ + + /* add all the starting basic types */ + + add_type(1, "int"); + add_type(1, "long"); + add_type(1, "short"); + add_type(1, "bool"); + + add_type(1, "u_int"); + add_type(1, "u_long"); + add_type(1, "u_short"); + +} + +char rpcgen_table_dcl[] = "struct rpcgen_table {\n\ + char *(*proc)();\n\ + xdrproc_t xdr_arg;\n\ + unsigned len_arg;\n\ + xdrproc_t xdr_res;\n\ + unsigned len_res;\n\ +};\n"; + + +static char * +generate_guard(pathname) + char *pathname; +{ + char *filename, *guard, *tmp; + + filename = strrchr(pathname, '/'); /* find last component */ + filename = ((filename == 0) ? pathname : filename + 1); + guard = strdup(filename); + /* convert to upper case */ + tmp = guard; + while (*tmp) { + if (islower(*tmp)) + *tmp = toupper(*tmp); + tmp++; + } + + guard = extendfile(guard, "_H_RPCGEN"); + return (guard); +} +/* + * Compile into an XDR header file + */ + +static void +h_output(infile, define, extend, outfile) + char *infile; + char *define; + int extend; + char *outfile; +{ + definition *def; + char *outfilename; + long tell; + char *guard; + list *l; + + open_input(infile, define); + outfilename = extend ? extendfile(infile, outfile) : outfile; + open_output(infile, outfilename); + add_warning(); + guard = generate_guard(outfilename ? outfilename : infile); + + f_print(fout, "#ifndef _%s\n#define _%s\n\n", guard, + guard); + + f_print(fout, "#define RPCGEN_VERSION\t%s\n\n", RPCGEN_VERSION); + f_print(fout, "#include \n\n"); + + tell = ftell(fout); + /* print data definitions */ + while ((def = get_definition()) != NULL) { + print_datadef(def); + } + + /* print function declarations. Do this after data definitions + * because they might be used as arguments for functions */ + for (l = defined; l != NULL; l = l->next) { + print_funcdef(l->val); + } + if (extend && tell == ftell(fout)) { + (void) unlink(outfilename); + } else + if (tblflag) { + f_print(fout, "%s", rpcgen_table_dcl); + } + f_print(fout, "\n#endif /* !_%s */\n", guard); +} +/* + * Compile into an RPC service + */ +static void +s_output(argc, argv, infile, define, extend, outfile, nomain, netflag) + int argc; + char *argv[]; + char *infile; + char *define; + int extend; + char *outfile; + int nomain; + int netflag; +{ + char *include; + definition *def; + int foundprogram = 0; + char *outfilename; + + open_input(infile, define); + outfilename = extend ? extendfile(infile, outfile) : outfile; + open_output(infile, outfilename); + add_warning(); + if (infile && (include = extendfile(infile, ".h"))) { + f_print(fout, "#include \"%s\"\n", include); + free(include); + } else + f_print(fout, "#include \n"); + + f_print(fout, "#include \n"); + f_print(fout, "#include \n"); + f_print(fout, "#include \n"); + f_print(fout, "#include \n"); + if (Cflag) { + f_print(fout, "#include \n"); + f_print(fout, + "#include \n"); + f_print(fout, "#include \n"); + } + f_print(fout, "#include \n"); + if (strcmp(svcclosetime, "-1") == 0) + indefinitewait = 1; + else + if (strcmp(svcclosetime, "0") == 0) + exitnow = 1; + else + if (inetdflag || pmflag) { + f_print(fout, "#include \n"); + timerflag = 1; + } + if (!tirpcflag && inetdflag) + f_print(fout, "#include \n"); + if (Cflag && (inetdflag || pmflag)) { + f_print(fout, "#ifdef __cplusplus\n"); + f_print(fout, "#include \n"); + f_print(fout, "#endif /* __cplusplus */\n"); + } + if (tirpcflag) + f_print(fout, "#include \n"); + + f_print(fout, "#include \n"); + if (tirpcflag) + f_print(fout, "#include \n"); + + if (inetdflag || !tirpcflag) { + f_print(fout, "#include \n"); + f_print(fout, "#include \n"); + } + if ((netflag || pmflag) && tirpcflag) { + f_print(fout, "#include \n"); + } + if ( /* timerflag && */ tirpcflag) + f_print(fout, "#include \n"); + if (logflag || inetdflag || pmflag) + f_print(fout, "#include \n"); + + /* for ANSI-C */ + f_print(fout, "\n#ifdef __STDC__\n#define SIG_PF void(*)(int)\n#endif\n"); + + f_print(fout, "\n#ifdef DEBUG\n#define RPC_SVC_FG\n#endif\n"); + if (timerflag) + f_print(fout, "\n#define _RPCSVC_CLOSEDOWN %s\n", svcclosetime); + while ((def = get_definition()) != NULL) { + foundprogram |= (def->def_kind == DEF_PROGRAM); + } + if (extend && !foundprogram) { + (void) unlink(outfilename); + return; + } + if (callerflag) /* EVAS */ + f_print(fout, "\nstatic SVCXPRT *caller;\n"); /* EVAS */ + write_most(infile, netflag, nomain); + if (!nomain) { + if (!do_registers(argc, argv)) { + if (outfilename) + (void) unlink(outfilename); + usage(); + } + write_rest(); + } +} +/* + * generate client side stubs + */ +static void +l_output(infile, define, extend, outfile) + char *infile; + char *define; + int extend; + char *outfile; +{ + char *include; + definition *def; + int foundprogram = 0; + char *outfilename; + + open_input(infile, define); + outfilename = extend ? extendfile(infile, outfile) : outfile; + open_output(infile, outfilename); + add_warning(); + if (Cflag) + f_print(fout, "#include \n"); + if (infile && (include = extendfile(infile, ".h"))) { + f_print(fout, "#include \"%s\"\n", include); + free(include); + } else + f_print(fout, "#include \n"); + while ((def = get_definition()) != NULL) { + foundprogram |= (def->def_kind == DEF_PROGRAM); + } + if (extend && !foundprogram) { + (void) unlink(outfilename); + return; + } + write_stubs(); +} +/* + * generate the dispatch table + */ +static void +t_output(infile, define, extend, outfile) + char *infile; + char *define; + int extend; + char *outfile; +{ + definition *def; + int foundprogram = 0; + char *outfilename; + + open_input(infile, define); + outfilename = extend ? extendfile(infile, outfile) : outfile; + open_output(infile, outfilename); + add_warning(); + while ((def = get_definition()) != NULL) { + foundprogram |= (def->def_kind == DEF_PROGRAM); + } + if (extend && !foundprogram) { + (void) unlink(outfilename); + return; + } + write_tables(); +} +/* sample routine for the server template */ +static void +svc_output(infile, define, extend, outfile) + char *infile; + char *define; + int extend; + char *outfile; +{ + definition *def; + char *include; + char *outfilename; + long tell; + + open_input(infile, define); + outfilename = extend ? extendfile(infile, outfile) : outfile; + checkfiles(infile, outfilename); /* check if outfile already + * exists. if so, print an + * error message and exit */ + open_output(infile, outfilename); + add_sample_msg(); + + if (infile && (include = extendfile(infile, ".h"))) { + f_print(fout, "#include \"%s\"\n", include); + free(include); + } else + f_print(fout, "#include \n"); + + tell = ftell(fout); + while ((def = get_definition()) != NULL) { + write_sample_svc(def); + } + if (extend && tell == ftell(fout)) { + (void) unlink(outfilename); + } +} + + +/* sample main routine for client */ +static void +clnt_output(infile, define, extend, outfile) + char *infile; + char *define; + int extend; + char *outfile; +{ + definition *def; + char *include; + char *outfilename; + long tell; + int has_program = 0; + + open_input(infile, define); + outfilename = extend ? extendfile(infile, outfile) : outfile; + checkfiles(infile, outfilename); /* check if outfile already + * exists. if so, print an + * error message and exit */ + + open_output(infile, outfilename); + add_sample_msg(); + if (infile && (include = extendfile(infile, ".h"))) { + f_print(fout, "#include \"%s\"\n", include); + free(include); + } else + f_print(fout, "#include \n"); + tell = ftell(fout); + while ((def = get_definition()) != NULL) { + has_program += write_sample_clnt(def); + } + + if (has_program) + write_sample_clnt_main(); + + if (extend && tell == ftell(fout)) { + (void) unlink(outfilename); + } +} +/* + * Perform registrations for service output + * Return 0 if failed; 1 otherwise. + */ +static int +do_registers(argc, argv) + int argc; + char *argv[]; +{ + int i; + + if (inetdflag || !tirpcflag) { + for (i = 1; i < argc; i++) { + if (streq(argv[i], "-s")) { + if (!check_nettype(argv[i + 1], valid_i_nettypes)) + return 0; + write_inetd_register(argv[i + 1]); + i++; + } + } + } else { + for (i = 1; i < argc; i++) + if (streq(argv[i], "-s")) { + if (!check_nettype(argv[i + 1], valid_ti_nettypes)) + return 0; + write_nettype_register(argv[i + 1]); + i++; + } else + if (streq(argv[i], "-n")) { + write_netid_register(argv[i + 1]); + i++; + } + } + return 1; +} +/* + * Add another argument to the arg list + */ +static void +addarg(cp) + char *cp; +{ + if (argcount >= ARGLISTLEN) { + f_print(stderr, "rpcgen: too many defines\n"); + crash(); + /* NOTREACHED */ + } + arglist[argcount++] = cp; + +} + +static void +putarg(where, cp) + char *cp; + int where; +{ + if (where >= ARGLISTLEN) { + f_print(stderr, "rpcgen: arglist coding error\n"); + crash(); + /* NOTREACHED */ + } + arglist[where] = cp; + +} +/* + * if input file is stdin and an output file is specified then complain + * if the file already exists. Otherwise the file may get overwritten + * If input file does not exist, exit with an error + */ + +static void +checkfiles(infile, outfile) + char *infile; + char *outfile; +{ + + struct stat buf; + + if (infile) /* infile ! = NULL */ + if (stat(infile, &buf) < 0) { + perror(infile); + crash(); + }; +#if 0 + if (outfile) { + if (stat(outfile, &buf) < 0) + return; /* file does not exist */ + else { + f_print(stderr, + "file '%s' already exists and may be overwritten\n", outfile); + crash(); + } + } +#endif +} +/* + * Parse command line arguments + */ +static int +parseargs(argc, argv, cmd) + int argc; + char *argv[]; + struct commandline *cmd; +{ + int i; + int j; + int c; + char flag[(1 << 8 * sizeof(char))]; + int nflags; + + cmdname = argv[0]; + cmd->infile = cmd->outfile = NULL; + if (argc < 2) { + return (0); + } + allfiles = 0; + flag['c'] = 0; + flag['h'] = 0; + flag['l'] = 0; + flag['m'] = 0; + flag['o'] = 0; + flag['s'] = 0; + flag['n'] = 0; + flag['t'] = 0; + flag['S'] = 0; + flag['C'] = 0; + for (i = 1; i < argc; i++) { + if (argv[i][0] != '-') { + if (cmd->infile) { + f_print(stderr, "Cannot specify more than one input file!\n"); + + return (0); + } + cmd->infile = argv[i]; + } else { + for (j = 1; argv[i][j] != 0; j++) { + c = argv[i][j]; + switch (c) { + case 'A': + callerflag = 1; + break; + case 'a': + allfiles = 1; + break; + case 'c': + case 'h': + case 'l': + case 'm': + case 't': + if (flag[c]) { + return (0); + } + flag[c] = 1; + break; + case 'S': + /* sample flag: Ss or Sc. Ss means set + * flag['S']; Sc means set flag['C']; */ + c = argv[i][++j]; /* get next char */ + if (c == 's') + c = 'S'; + else + if (c == 'c') + c = 'C'; + else + return (0); + + if (flag[c]) { + return (0); + } + flag[c] = 1; + break; + case 'C': /* ANSI C syntax */ + Cflag = 1; + break; + + case 'b': /* turn TIRPC flag off for + * generating backward + * compatible */ + tirpcflag = 0; + break; + + case 'I': + inetdflag = 1; + break; + case 'N': + newstyle = 1; + break; + case 'L': + logflag = 1; + break; + case 'K': + if (++i == argc) { + return (0); + } + svcclosetime = argv[i]; + goto nextarg; + case 'T': + tblflag = 1; + break; + case 'i': + if (++i == argc) { + return (0); + } + doinline = atoi(argv[i]); + goto nextarg; + case 'n': + case 'o': + case 's': + if (argv[i][j - 1] != '-' || + argv[i][j + 1] != 0) { + return (0); + } + flag[c] = 1; + if (++i == argc) { + return (0); + } + if (c == 's') { + if (!streq(argv[i], "udp") && + !streq(argv[i], "tcp")) { + return (0); + } + } else + if (c == 'o') { + if (cmd->outfile) { + return (0); + } + cmd->outfile = argv[i]; + } + goto nextarg; + case 'D': + if (argv[i][j - 1] != '-') { + return (0); + } + (void) addarg(argv[i]); + goto nextarg; + case 'Y': + if (++i == argc) { + return (0); + } + (void) strcpy(pathbuf, argv[i]); + (void) strcat(pathbuf, "/cpp"); + CPP = pathbuf; + cppDefined = 1; + goto nextarg; + + + + default: + return (0); + } + } + nextarg: + ; + } + } + + cmd->cflag = flag['c']; + cmd->hflag = flag['h']; + cmd->lflag = flag['l']; + cmd->mflag = flag['m']; + cmd->nflag = flag['n']; + cmd->sflag = flag['s']; + cmd->tflag = flag['t']; + cmd->Ssflag = flag['S']; + cmd->Scflag = flag['C']; + + if (tirpcflag) { + pmflag = inetdflag ? 0 : 1; /* pmflag or inetdflag is + * always TRUE */ + if ((inetdflag && cmd->nflag)) { /* netid not allowed + * with inetdflag */ + f_print(stderr, "Cannot use netid flag with inetd flag!\n"); + return (0); + } + } else { /* 4.1 mode */ + pmflag = 0; /* set pmflag only in tirpcmode */ + inetdflag = 1; /* inetdflag is TRUE by default */ + if (cmd->nflag) { /* netid needs TIRPC */ + f_print(stderr, "Cannot use netid flag without TIRPC!\n"); + return (0); + } + } + + if (newstyle && (tblflag || cmd->tflag)) { + f_print(stderr, "Cannot use table flags with newstyle!\n"); + return (0); + } + /* check no conflicts with file generation flags */ + nflags = cmd->cflag + cmd->hflag + cmd->lflag + cmd->mflag + + cmd->sflag + cmd->nflag + cmd->tflag + cmd->Ssflag + cmd->Scflag; + + if (nflags == 0) { + if (cmd->outfile != NULL || cmd->infile == NULL) { + return (0); + } + } else + if (nflags > 1) { + f_print(stderr, "Cannot have more than one file generation flag!\n"); + return (0); + } + return (1); +} + +static void +usage() +{ + f_print(stderr, "usage: %s infile\n", cmdname); + f_print(stderr, "\t%s [-a][-b][-C][-Dname[=value]] -i size [-I [-K seconds]] [-A][-L][-M toolkit][-N][-T] infile\n", + cmdname); + f_print(stderr, "\t%s [-c | -h | -l | -m | -t | -Sc | -Ss] [-o outfile] [infile]\n", + cmdname); + f_print(stderr, "\t%s [-s nettype]* [-o outfile] [infile]\n", cmdname); + f_print(stderr, "\t%s [-n netid]* [-o outfile] [infile]\n", cmdname); + options_usage(); + exit(1); +} + +static void +options_usage() +{ + f_print(stderr, "options:\n"); + f_print(stderr, "-A\t\tgenerate svc_caller() function\n"); + f_print(stderr, "-a\t\tgenerate all files, including samples\n"); + f_print(stderr, "-b\t\tbackward compatibility mode (generates code for SunOS 4.1)\n"); + f_print(stderr, "-c\t\tgenerate XDR routines\n"); + f_print(stderr, "-C\t\tANSI C mode\n"); + f_print(stderr, "-Dname[=value]\tdefine a symbol (same as #define)\n"); + f_print(stderr, "-h\t\tgenerate header file\n"); + f_print(stderr, "-i size\t\tsize at which to start generating inline code\n"); + f_print(stderr, "-I\t\tgenerate code for inetd support in server (for SunOS 4.1)\n"); + f_print(stderr, "-K seconds\tserver exits after K seconds of inactivity\n"); + f_print(stderr, "-l\t\tgenerate client side stubs\n"); + f_print(stderr, "-L\t\tserver errors will be printed to syslog\n"); + f_print(stderr, "-m\t\tgenerate server side stubs\n"); + f_print(stderr, "-n netid\tgenerate server code that supports named netid\n"); + f_print(stderr, "-N\t\tsupports multiple arguments and call-by-value\n"); + f_print(stderr, "-o outfile\tname of the output file\n"); + f_print(stderr, "-s nettype\tgenerate server code that supports named nettype\n"); + f_print(stderr, "-Sc\t\tgenerate sample client code that uses remote procedures\n"); + f_print(stderr, "-Ss\t\tgenerate sample server code that defines remote procedures\n"); + f_print(stderr, "-t\t\tgenerate RPC dispatch table\n"); + f_print(stderr, "-T\t\tgenerate code to support RPC dispatch tables\n"); + f_print(stderr, "-Y path\t\tdirectory name to find C preprocessor (cpp)\n"); + + exit(1); +} diff --git a/developer_cmds/rpcgen/rpc_parse.c b/developer_cmds/rpcgen/rpc_parse.c new file mode 100644 index 0000000..db0c1f1 --- /dev/null +++ b/developer_cmds/rpcgen/rpc_parse.c @@ -0,0 +1,643 @@ +/* $NetBSD: rpc_parse.c,v 1.9 1998/02/11 23:11:18 lukem Exp $ */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user or with the express written consent of + * Sun Microsystems, Inc. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)rpc_parse.c 1.8 89/02/22 (C) 1987 SMI"; +#else +__RCSID("$NetBSD: rpc_parse.c,v 1.9 1998/02/11 23:11:18 lukem Exp $"); +#endif +#endif + +/* + * rpc_parse.c, Parser for the RPC protocol compiler + * Copyright (C) 1987 Sun Microsystems, Inc. + */ +#include +#include +#include +#include "rpc/types.h" +#include "rpc_scan.h" +#include "rpc_parse.h" +#include "rpc_util.h" + +#define ARGNAME "arg" + +static void isdefined __P((definition *)); +static void def_struct __P((definition *)); +static void def_program __P((definition *)); +static void def_enum __P((definition *)); +static void def_const __P((definition *)); +static void def_union __P((definition *)); +static void check_type_name __P((char *, int)); +static void def_typedef __P((definition *)); +static void get_declaration __P((declaration *, defkind)); +static void get_prog_declaration __P((declaration *, defkind, int)); +static void get_type __P((char **, char **, defkind)); +static void unsigned_dec __P((char **)); + +/* + * return the next definition you see + */ +definition * +get_definition() +{ + definition *defp; + token tok; + + defp = ALLOC(definition); + get_token(&tok); + switch (tok.kind) { + case TOK_STRUCT: + def_struct(defp); + break; + case TOK_UNION: + def_union(defp); + break; + case TOK_TYPEDEF: + def_typedef(defp); + break; + case TOK_ENUM: + def_enum(defp); + break; + case TOK_PROGRAM: + def_program(defp); + break; + case TOK_CONST: + def_const(defp); + break; + case TOK_EOF: + return (NULL); + default: + error("definition keyword expected"); + } + scan(TOK_SEMICOLON, &tok); + isdefined(defp); + return (defp); +} + +static void +isdefined(defp) + definition *defp; +{ + STOREVAL(&defined, defp); +} + +static void +def_struct(defp) + definition *defp; +{ + token tok; + declaration dec; + decl_list *decls; + decl_list **tailp; + + defp->def_kind = DEF_STRUCT; + + scan(TOK_IDENT, &tok); + defp->def_name = tok.str; + scan(TOK_LBRACE, &tok); + tailp = &defp->def.st.decls; + do { + get_declaration(&dec, DEF_STRUCT); + decls = ALLOC(decl_list); + decls->decl = dec; + *tailp = decls; + tailp = &decls->next; + scan(TOK_SEMICOLON, &tok); + peek(&tok); + } while (tok.kind != TOK_RBRACE); + get_token(&tok); + *tailp = NULL; +} + +static void +def_program(defp) + definition *defp; +{ + token tok; + declaration dec; + decl_list *decls; + decl_list **tailp; + version_list *vlist; + version_list **vtailp; + proc_list *plist; + proc_list **ptailp; + int num_args; + bool_t isvoid = FALSE; /* whether first argument is void */ + defp->def_kind = DEF_PROGRAM; + scan(TOK_IDENT, &tok); + defp->def_name = tok.str; + scan(TOK_LBRACE, &tok); + vtailp = &defp->def.pr.versions; + tailp = &defp->def.st.decls; + scan(TOK_VERSION, &tok); + do { + scan(TOK_IDENT, &tok); + vlist = ALLOC(version_list); + vlist->vers_name = tok.str; + scan(TOK_LBRACE, &tok); + ptailp = &vlist->procs; + do { + /* get result type */ + plist = ALLOC(proc_list); + get_type(&plist->res_prefix, &plist->res_type, + DEF_PROGRAM); + if (streq(plist->res_type, "opaque")) { + error("illegal result type"); + } + scan(TOK_IDENT, &tok); + plist->proc_name = tok.str; + scan(TOK_LPAREN, &tok); + /* get args - first one */ + num_args = 1; + isvoid = FALSE; + /* type of DEF_PROGRAM in the first + * get_prog_declaration and DEF_STURCT in the next + * allows void as argument if it is the only argument */ + get_prog_declaration(&dec, DEF_PROGRAM, num_args); + if (streq(dec.type, "void")) + isvoid = TRUE; + decls = ALLOC(decl_list); + plist->args.decls = decls; + decls->decl = dec; + tailp = &decls->next; + /* get args */ + while (peekscan(TOK_COMMA, &tok)) { + num_args++; + get_prog_declaration(&dec, DEF_STRUCT, + num_args); + decls = ALLOC(decl_list); + decls->decl = dec; + *tailp = decls; + if (streq(dec.type, "void")) + isvoid = TRUE; + tailp = &decls->next; + } + /* multiple arguments are only allowed in newstyle */ + if (!newstyle && num_args > 1) { + error("only one argument is allowed"); + } + if (isvoid && num_args > 1) { + error("illegal use of void in program definition"); + } + *tailp = NULL; + scan(TOK_RPAREN, &tok); + scan(TOK_EQUAL, &tok); + scan_num(&tok); + scan(TOK_SEMICOLON, &tok); + plist->proc_num = tok.str; + plist->arg_num = num_args; + *ptailp = plist; + ptailp = &plist->next; + peek(&tok); + } while (tok.kind != TOK_RBRACE); + *ptailp = NULL; + *vtailp = vlist; + vtailp = &vlist->next; + scan(TOK_RBRACE, &tok); + scan(TOK_EQUAL, &tok); + scan_num(&tok); + vlist->vers_num = tok.str; + /* make the argument structure name for each arg */ + for (plist = vlist->procs; plist != NULL; + plist = plist->next) { + plist->args.argname = make_argname(plist->proc_name, + vlist->vers_num); + /* free the memory ?? */ + } + scan(TOK_SEMICOLON, &tok); + scan2(TOK_VERSION, TOK_RBRACE, &tok); + } while (tok.kind == TOK_VERSION); + scan(TOK_EQUAL, &tok); + scan_num(&tok); + defp->def.pr.prog_num = tok.str; + *vtailp = NULL; +} + + +static void +def_enum(defp) + definition *defp; +{ + token tok; + enumval_list *elist; + enumval_list **tailp; + + defp->def_kind = DEF_ENUM; + scan(TOK_IDENT, &tok); + defp->def_name = tok.str; + scan(TOK_LBRACE, &tok); + tailp = &defp->def.en.vals; + do { + scan(TOK_IDENT, &tok); + elist = ALLOC(enumval_list); + elist->name = tok.str; + elist->assignment = NULL; + scan3(TOK_COMMA, TOK_RBRACE, TOK_EQUAL, &tok); + if (tok.kind == TOK_EQUAL) { + scan_num(&tok); + elist->assignment = tok.str; + scan2(TOK_COMMA, TOK_RBRACE, &tok); + } + *tailp = elist; + tailp = &elist->next; + } while (tok.kind != TOK_RBRACE); + *tailp = NULL; +} + +static void +def_const(defp) + definition *defp; +{ + token tok; + + defp->def_kind = DEF_CONST; + scan(TOK_IDENT, &tok); + defp->def_name = tok.str; + scan(TOK_EQUAL, &tok); + scan2(TOK_IDENT, TOK_STRCONST, &tok); + defp->def.co = tok.str; +} + +static void +def_union(defp) + definition *defp; +{ + token tok; + declaration dec; + case_list *cases; + case_list **tailp; + int flag; + + defp->def_kind = DEF_UNION; + scan(TOK_IDENT, &tok); + defp->def_name = tok.str; + scan(TOK_SWITCH, &tok); + scan(TOK_LPAREN, &tok); + get_declaration(&dec, DEF_UNION); + defp->def.un.enum_decl = dec; + tailp = &defp->def.un.cases; + scan(TOK_RPAREN, &tok); + scan(TOK_LBRACE, &tok); + scan(TOK_CASE, &tok); + while (tok.kind == TOK_CASE) { + scan2(TOK_IDENT, TOK_CHARCONST, &tok); + cases = ALLOC(case_list); + cases->case_name = tok.str; + scan(TOK_COLON, &tok); + /* now peek at next token */ + flag = 0; + if (peekscan(TOK_CASE, &tok)) { + + do { + scan2(TOK_IDENT, TOK_CHARCONST, &tok); + cases->contflag = 1; /* continued case + * statement */ + *tailp = cases; + tailp = &cases->next; + cases = ALLOC(case_list); + cases->case_name = tok.str; + scan(TOK_COLON, &tok); + + } while (peekscan(TOK_CASE, &tok)); + } else + if (flag) { + + *tailp = cases; + tailp = &cases->next; + cases = ALLOC(case_list); + }; + + get_declaration(&dec, DEF_UNION); + cases->case_decl = dec; + cases->contflag = 0; /* no continued case statement */ + *tailp = cases; + tailp = &cases->next; + scan(TOK_SEMICOLON, &tok); + + scan3(TOK_CASE, TOK_DEFAULT, TOK_RBRACE, &tok); + } + *tailp = NULL; + if (tok.kind == TOK_DEFAULT) { + scan(TOK_COLON, &tok); + get_declaration(&dec, DEF_UNION); + defp->def.un.default_decl = ALLOC(declaration); + *defp->def.un.default_decl = dec; + scan(TOK_SEMICOLON, &tok); + scan(TOK_RBRACE, &tok); + } else { + defp->def.un.default_decl = NULL; + } +} + +static char *reserved_words[] = { + "array", + "bytes", + "destroy", + "free", + "getpos", + "inline", + "pointer", + "reference", + "setpos", + "sizeof", + "union", + "vector", + NULL +}; + +static char *reserved_types[] = { + "opaque", + "string", + NULL +}; +/* check that the given name is not one that would eventually result in + xdr routines that would conflict with internal XDR routines. */ +static void +check_type_name(name, new_type) + int new_type; + char *name; +{ + int i; + char tmp[100]; + + for (i = 0; reserved_words[i] != NULL; i++) { + if (strcmp(name, reserved_words[i]) == 0) { + sprintf(tmp, + "illegal (reserved) name :\'%s\' in type definition", name); + error(tmp); + } + } + if (new_type) { + for (i = 0; reserved_types[i] != NULL; i++) { + if (strcmp(name, reserved_types[i]) == 0) { + sprintf(tmp, + "illegal (reserved) name :\'%s\' in type definition", name); + error(tmp); + } + } + } +} + +static void +def_typedef(defp) + definition *defp; +{ + declaration dec; + + defp->def_kind = DEF_TYPEDEF; + get_declaration(&dec, DEF_TYPEDEF); + defp->def_name = dec.name; + check_type_name(dec.name, 1); + defp->def.ty.old_prefix = dec.prefix; + defp->def.ty.old_type = dec.type; + defp->def.ty.rel = dec.rel; + defp->def.ty.array_max = dec.array_max; +} + +static void +get_declaration(dec, dkind) + declaration *dec; + defkind dkind; +{ + token tok; + + get_type(&dec->prefix, &dec->type, dkind); + dec->rel = REL_ALIAS; + if (streq(dec->type, "void")) { + return; + } + check_type_name(dec->type, 0); + + scan2(TOK_STAR, TOK_IDENT, &tok); + if (tok.kind == TOK_STAR) { + dec->rel = REL_POINTER; + scan(TOK_IDENT, &tok); + } + dec->name = tok.str; + if (peekscan(TOK_LBRACKET, &tok)) { + if (dec->rel == REL_POINTER) { + error("no array-of-pointer declarations -- use typedef"); + } + dec->rel = REL_VECTOR; + scan_num(&tok); + dec->array_max = tok.str; + scan(TOK_RBRACKET, &tok); + } else + if (peekscan(TOK_LANGLE, &tok)) { + if (dec->rel == REL_POINTER) { + error("no array-of-pointer declarations -- use typedef"); + } + dec->rel = REL_ARRAY; + if (peekscan(TOK_RANGLE, &tok)) { + dec->array_max = "~0"; /* unspecified size, use + * max */ + } else { + scan_num(&tok); + dec->array_max = tok.str; + scan(TOK_RANGLE, &tok); + } + } + if (streq(dec->type, "opaque")) { + if (dec->rel != REL_ARRAY && dec->rel != REL_VECTOR) { + error("array declaration expected"); + } + } else + if (streq(dec->type, "string")) { + if (dec->rel != REL_ARRAY) { + error("variable-length array declaration expected"); + } + } +} + +static void +get_prog_declaration(dec, dkind, num) + declaration *dec; + defkind dkind; + int num; /* arg number */ +{ + token tok; + char name[10]; /* argument name */ + + if (dkind == DEF_PROGRAM) { + peek(&tok); + if (tok.kind == TOK_RPAREN) { /* no arguments */ + dec->rel = REL_ALIAS; + dec->type = "void"; + dec->prefix = NULL; + dec->name = NULL; + return; + } + } + get_type(&dec->prefix, &dec->type, dkind); + dec->rel = REL_ALIAS; + if (peekscan(TOK_IDENT, &tok)) /* optional name of argument */ + strcpy(name, tok.str); + else + sprintf(name, "%s%d", ARGNAME, num); /* default name of + * argument */ + + dec->name = (char *) strdup(name); + + if (streq(dec->type, "void")) { + return; + } + if (streq(dec->type, "opaque")) { + error("opaque -- illegal argument type"); + } + if (peekscan(TOK_STAR, &tok)) { + if (streq(dec->type, "string")) { + error("pointer to string not allowed in program arguments\n"); + } + dec->rel = REL_POINTER; + if (peekscan(TOK_IDENT, &tok)) /* optional name of argument */ + dec->name = (char *) strdup(tok.str); + } + if (peekscan(TOK_LANGLE, &tok)) { + if (!streq(dec->type, "string")) { + error("arrays cannot be declared as arguments to procedures -- use typedef"); + } + dec->rel = REL_ARRAY; + if (peekscan(TOK_RANGLE, &tok)) { + dec->array_max = "~0"; /* unspecified size, use max */ + } else { + scan_num(&tok); + dec->array_max = tok.str; + scan(TOK_RANGLE, &tok); + } + } + if (streq(dec->type, "string")) { + if (dec->rel != REL_ARRAY) { /* .x specifies just string as + * type of argument - make it + * string<> */ + dec->rel = REL_ARRAY; + dec->array_max = "~0"; /* unspecified size, use max */ + } + } +} + + + +static void +get_type(prefixp, typep, dkind) + char **prefixp; + char **typep; + defkind dkind; +{ + token tok; + + *prefixp = NULL; + get_token(&tok); + switch (tok.kind) { + case TOK_IDENT: + *typep = tok.str; + break; + case TOK_STRUCT: + case TOK_ENUM: + case TOK_UNION: + *prefixp = tok.str; + scan(TOK_IDENT, &tok); + *typep = tok.str; + break; + case TOK_UNSIGNED: + unsigned_dec(typep); + break; + case TOK_SHORT: + *typep = "short"; + (void) peekscan(TOK_INT, &tok); + break; + case TOK_LONG: + *typep = "long"; + (void) peekscan(TOK_INT, &tok); + break; + case TOK_HYPER: + *typep = "int64_t"; + (void) peekscan(TOK_INT, &tok); + break; + case TOK_VOID: + if (dkind != DEF_UNION && dkind != DEF_PROGRAM) { + error("voids allowed only inside union and program definitions with one argument"); + } + *typep = tok.str; + break; + case TOK_STRING: + case TOK_OPAQUE: + case TOK_CHAR: + case TOK_INT: + case TOK_FLOAT: + case TOK_DOUBLE: + case TOK_QUAD: + case TOK_BOOL: + *typep = tok.str; + break; + default: + error("expected type specifier"); + } +} + +static void +unsigned_dec(typep) + char **typep; +{ + token tok; + + peek(&tok); + switch (tok.kind) { + case TOK_CHAR: + get_token(&tok); + *typep = "u_char"; + break; + case TOK_SHORT: + get_token(&tok); + *typep = "u_short"; + (void) peekscan(TOK_INT, &tok); + break; + case TOK_LONG: + get_token(&tok); + *typep = "u_long"; + (void) peekscan(TOK_INT, &tok); + break; + case TOK_HYPER: + get_token(&tok); + *typep = "u_int64_t"; + (void) peekscan(TOK_INT, &tok); + break; + case TOK_INT: + get_token(&tok); + *typep = "u_int"; + break; + default: + *typep = "u_int"; + break; + } +} diff --git a/developer_cmds/rpcgen/rpc_parse.h b/developer_cmds/rpcgen/rpc_parse.h new file mode 100644 index 0000000..e235bf5 --- /dev/null +++ b/developer_cmds/rpcgen/rpc_parse.h @@ -0,0 +1,168 @@ +/* $NetBSD: rpc_parse.h,v 1.4 1997/10/11 21:01:42 christos Exp $ */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user or with the express written consent of + * Sun Microsystems, Inc. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* @(#)rpc_parse.h 1.3 90/08/29 (C) 1987 SMI */ + +/* + * rpc_parse.h, Definitions for the RPCL parser + */ + +enum defkind { + DEF_CONST, + DEF_STRUCT, + DEF_UNION, + DEF_ENUM, + DEF_TYPEDEF, + DEF_PROGRAM +}; +typedef enum defkind defkind; + +typedef char *const_def; + +enum relation { + REL_VECTOR, /* fixed length array */ + REL_ARRAY, /* variable length array */ + REL_POINTER, /* pointer */ + REL_ALIAS, /* simple */ +}; +typedef enum relation relation; + +struct typedef_def { + char *old_prefix; + char *old_type; + relation rel; + char *array_max; +}; +typedef struct typedef_def typedef_def; + +struct enumval_list { + char *name; + char *assignment; + struct enumval_list *next; +}; +typedef struct enumval_list enumval_list; + +struct enum_def { + enumval_list *vals; +}; +typedef struct enum_def enum_def; + +struct declaration { + char *prefix; + char *type; + char *name; + relation rel; + char *array_max; +}; +typedef struct declaration declaration; + +struct decl_list { + declaration decl; + struct decl_list *next; +}; +typedef struct decl_list decl_list; + +struct struct_def { + decl_list *decls; +}; +typedef struct struct_def struct_def; + +struct case_list { + char *case_name; + int contflag; + declaration case_decl; + struct case_list *next; +}; +typedef struct case_list case_list; + +struct union_def { + declaration enum_decl; + case_list *cases; + declaration *default_decl; +}; +typedef struct union_def union_def; + +struct arg_list { + char *argname; /* name of struct for arg*/ + decl_list *decls; +}; + +typedef struct arg_list arg_list; + +struct proc_list { + char *proc_name; + char *proc_num; + arg_list args; + int arg_num; + char *res_type; + char *res_prefix; + struct proc_list *next; +}; +typedef struct proc_list proc_list; + +struct version_list { + char *vers_name; + char *vers_num; + proc_list *procs; + struct version_list *next; +}; +typedef struct version_list version_list; + +struct program_def { + char *prog_num; + version_list *versions; +}; +typedef struct program_def program_def; + +struct definition { + char *def_name; + defkind def_kind; + union { + const_def co; + struct_def st; + union_def un; + enum_def en; + typedef_def ty; + program_def pr; + } def; +}; +typedef struct definition definition; + +definition *get_definition __P((void)); + +struct bas_type +{ + char *name; + int length; + struct bas_type *next; +}; + +typedef struct bas_type bas_type; diff --git a/developer_cmds/rpcgen/rpc_sample.c b/developer_cmds/rpcgen/rpc_sample.c new file mode 100644 index 0000000..3fee135 --- /dev/null +++ b/developer_cmds/rpcgen/rpc_sample.c @@ -0,0 +1,261 @@ +/* $NetBSD: rpc_sample.c,v 1.5 1997/10/18 10:54:01 lukem Exp $ */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user or with the express written consent of + * Sun Microsystems, Inc. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)rpc_sample.c 1.1 90/08/30 (C) 1987 SMI"; +#else +__RCSID("$NetBSD: rpc_sample.c,v 1.5 1997/10/18 10:54:01 lukem Exp $"); +#endif +#endif + +/* + * rpc_sample.c, Sample client-server code outputter for the RPC protocol compiler + */ + +#include +#include +#include "rpc_scan.h" +#include "rpc_parse.h" +#include "rpc_util.h" + +static char RQSTP[] = "rqstp"; + +static void write_sample_client __P((char *, version_list *)); +static void write_sample_server __P((definition *)); +static void return_type __P((proc_list *)); + +void +write_sample_svc(def) + definition *def; +{ + + if (def->def_kind != DEF_PROGRAM) + return; + write_sample_server(def); +} + + +int +write_sample_clnt(def) + definition *def; +{ + version_list *vp; + int count = 0; + + if (def->def_kind != DEF_PROGRAM) + return (0); + /* generate sample code for each version */ + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) { + write_sample_client(def->def_name, vp); + ++count; + } + return (count); +} + + +static void +write_sample_client(program_name, vp) + char *program_name; + version_list *vp; +{ + proc_list *proc; + int i; + decl_list *l; + + f_print(fout, "\n\nvoid\n"); + pvname(program_name, vp->vers_num); + if (Cflag) + f_print(fout, "( char* host )\n{\n"); + else + f_print(fout, "(host)\nchar *host;\n{\n"); + f_print(fout, "\tCLIENT *clnt;\n"); + + i = 0; + for (proc = vp->procs; proc != NULL; proc = proc->next) { + f_print(fout, "\t"); + ptype(proc->res_prefix, proc->res_type, 1); + f_print(fout, " *result_%d;\n", ++i); + /* print out declarations for arguments */ + if (proc->arg_num < 2 && !newstyle) { + f_print(fout, "\t"); + if (!streq(proc->args.decls->decl.type, "void")) + ptype(proc->args.decls->decl.prefix, proc->args.decls->decl.type, 1); + else + f_print(fout, "char* "); /* cannot have "void" + * type */ + f_print(fout, " "); + pvname(proc->proc_name, vp->vers_num); + f_print(fout, "_arg;\n"); + } else + if (!streq(proc->args.decls->decl.type, "void")) { + for (l = proc->args.decls; l != NULL; l = l->next) { + f_print(fout, "\t"); + ptype(l->decl.prefix, l->decl.type, 1); + f_print(fout, " "); + pvname(proc->proc_name, vp->vers_num); + f_print(fout, "_%s;\n", l->decl.name); +/* pdeclaration(proc->args.argname, &l->decl, 1, ";\n" );*/ + } + } + } + + /* generate creation of client handle */ + f_print(fout, "\tclnt = clnt_create(host, %s, %s, \"%s\");\n", + program_name, vp->vers_name, tirpcflag ? "netpath" : "udp"); + f_print(fout, "\tif (clnt == NULL) {\n"); + f_print(fout, "\t\tclnt_pcreateerror(host);\n"); + f_print(fout, "\t\texit(1);\n\t}\n"); + + /* generate calls to procedures */ + i = 0; + for (proc = vp->procs; proc != NULL; proc = proc->next) { + f_print(fout, "\tresult_%d = ", ++i); + pvname(proc->proc_name, vp->vers_num); + if (proc->arg_num < 2 && !newstyle) { + f_print(fout, "("); + if (streq(proc->args.decls->decl.type, "void")) /* cast to void* */ + f_print(fout, "(void*)"); + f_print(fout, "&"); + pvname(proc->proc_name, vp->vers_num); + f_print(fout, "_arg, clnt);\n"); + } else + if (streq(proc->args.decls->decl.type, "void")) { + f_print(fout, "(clnt);\n"); + } else { + f_print(fout, "("); + for (l = proc->args.decls; l != NULL; l = l->next) { + pvname(proc->proc_name, vp->vers_num); + f_print(fout, "_%s, ", l->decl.name); + } + f_print(fout, "clnt);\n"); + } + f_print(fout, "\tif (result_%d == NULL) {\n", i); + f_print(fout, "\t\tclnt_perror(clnt, \"call failed:\");\n"); + f_print(fout, "\t}\n"); + } + + f_print(fout, "\tclnt_destroy( clnt );\n"); + f_print(fout, "}\n"); +} + +static void +write_sample_server(def) + definition *def; +{ + version_list *vp; + proc_list *proc; + + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) { + for (proc = vp->procs; proc != NULL; proc = proc->next) { + f_print(fout, "\n"); +/* if( Cflag ) + f_print( fout, "extern \"C\"{\n"); +*/ + return_type(proc); + f_print(fout, "*\n"); + if (Cflag) + pvname_svc(proc->proc_name, vp->vers_num); + else + pvname(proc->proc_name, vp->vers_num); + printarglist(proc, RQSTP, "struct svc_req *"); + + f_print(fout, "{\n"); + f_print(fout, "\n\tstatic "); + if (!streq(proc->res_type, "void")) + return_type(proc); + else + f_print(fout, "char*"); /* cannot have void type */ + f_print(fout, " result;\n"); + f_print(fout, + "\n\t/*\n\t * insert server code here\n\t */\n\n"); + if (!streq(proc->res_type, "void")) + f_print(fout, "\treturn(&result);\n}\n"); + else /* cast back to void * */ + f_print(fout, "\treturn((void*) &result);\n}\n"); +/* if( Cflag) + f_print( fout, "};\n"); +*/ + + } + } +} + +static void +return_type(plist) + proc_list *plist; +{ + ptype(plist->res_prefix, plist->res_type, 1); +} + +void +add_sample_msg() +{ + f_print(fout, "/*\n"); + f_print(fout, " * This is sample code generated by rpcgen.\n"); + f_print(fout, " * These are only templates and you can use them\n"); + f_print(fout, " * as a guideline for developing your own functions.\n"); + f_print(fout, " */\n\n"); +} + +void +write_sample_clnt_main() +{ + list *l; + definition *def; + version_list *vp; + + f_print(fout, "\n\n"); + if (Cflag) + f_print(fout, "main( int argc, char* argv[] )\n{\n"); + else + f_print(fout, "main(argc, argv)\nint argc;\nchar *argv[];\n{\n"); + + f_print(fout, "\tchar *host;"); + f_print(fout, "\n\n\tif(argc < 2) {"); + f_print(fout, "\n\t\tprintf(\"usage: %%s server_host\\n\", argv[0]);\n"); + f_print(fout, "\t\texit(1);\n\t}"); + f_print(fout, "\n\thost = argv[1];\n"); + + for (l = defined; l != NULL; l = l->next) { + def = l->val; + if (def->def_kind != DEF_PROGRAM) { + continue; + } + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) { + f_print(fout, "\t"); + pvname(def->def_name, vp->vers_num); + f_print(fout, "( host );\n"); + } + } + f_print(fout, "}\n"); +} diff --git a/developer_cmds/rpcgen/rpc_scan.c b/developer_cmds/rpcgen/rpc_scan.c new file mode 100644 index 0000000..4130107 --- /dev/null +++ b/developer_cmds/rpcgen/rpc_scan.c @@ -0,0 +1,521 @@ +/* $NetBSD: rpc_scan.c,v 1.6 1997/10/18 10:54:05 lukem Exp $ */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user or with the express written consent of + * Sun Microsystems, Inc. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)rpc_scan.c 1.11 89/02/22 (C) 1987 SMI"; +#else +__RCSID("$NetBSD: rpc_scan.c,v 1.6 1997/10/18 10:54:05 lukem Exp $"); +#endif +#endif + +/* + * rpc_scan.c, Scanner for the RPC protocol compiler + * Copyright (C) 1987, Sun Microsystems, Inc. + */ +#include +#include +#include +#include +#include "rpc_scan.h" +#include "rpc_parse.h" +#include "rpc_util.h" + +#define startcomment(where) (where[0] == '/' && where[1] == '*') +#define endcomment(where) (where[-1] == '*' && where[0] == '/') + +static void unget_token __P((token *)); +static void findstrconst __P((char **, char **)); +static void findchrconst __P((char **, char **)); +static void findconst __P((char **, char **)); +static void findkind __P((char **, token *)); +static int cppline __P((char *)); +static int directive __P((char *)); +static void printdirective __P((char *)); +static void docppline __P((char *, int *, char **)); + +static int pushed = 0; /* is a token pushed */ +static token lasttok; /* last token, if pushed */ + +/* + * scan expecting 1 given token + */ +void +scan(expect, tokp) + tok_kind expect; + token *tokp; +{ + get_token(tokp); + if (tokp->kind != expect) { + expected1(expect); + } +} +/* + * scan expecting any of the 2 given tokens + */ +void +scan2(expect1, expect2, tokp) + tok_kind expect1; + tok_kind expect2; + token *tokp; +{ + get_token(tokp); + if (tokp->kind != expect1 && tokp->kind != expect2) { + expected2(expect1, expect2); + } +} +/* + * scan expecting any of the 3 given token + */ +void +scan3(expect1, expect2, expect3, tokp) + tok_kind expect1; + tok_kind expect2; + tok_kind expect3; + token *tokp; +{ + get_token(tokp); + if (tokp->kind != expect1 && tokp->kind != expect2 + && tokp->kind != expect3) { + expected3(expect1, expect2, expect3); + } +} +/* + * scan expecting a constant, possibly symbolic + */ +void +scan_num(tokp) + token *tokp; +{ + get_token(tokp); + switch (tokp->kind) { + case TOK_IDENT: + break; + default: + error("constant or identifier expected"); + } +} +/* + * Peek at the next token + */ +void +peek(tokp) + token *tokp; +{ + get_token(tokp); + unget_token(tokp); +} +/* + * Peek at the next token and scan it if it matches what you expect + */ +int +peekscan(expect, tokp) + tok_kind expect; + token *tokp; +{ + peek(tokp); + if (tokp->kind == expect) { + get_token(tokp); + return (1); + } + return (0); +} +/* + * Get the next token, printing out any directive that are encountered. + */ +void +get_token(tokp) + token *tokp; +{ + int commenting; + int stat = 0; + + if (pushed) { + pushed = 0; + *tokp = lasttok; + return; + } + commenting = 0; + for (;;) { + if (*where == 0) { + for (;;) { + if (!fgets(curline, MAXLINESIZE, fin)) { + tokp->kind = TOK_EOF; + /* now check if cpp returned non NULL value */ + waitpid(childpid, &stat, WUNTRACED); + if (stat > 0) { + /* Set return value from rpcgen */ + nonfatalerrors = stat >> 8; + } + *where = 0; + return; + } + linenum++; + if (commenting) { + break; + } else + /* skip lines beginning with #pragma */ + if (!strncmp(curline, "#pragma", 7)) *curline = 0; + else if (cppline(curline)) { + docppline(curline, &linenum, + &infilename); + } else + if (directive(curline)) { + printdirective(curline); + } else { + break; + } + } + where = curline; + } else + if (isspace(*where)) { + while (isspace(*where)) { + where++; /* eat */ + } + } else + if (commenting) { + for (where++; *where; where++) { + if (endcomment(where)) { + where++; + commenting--; + break; + } + } + } else + if (startcomment(where)) { + where += 2; + commenting++; + } else { + break; + } + } + + /* + * 'where' is not whitespace, comment or directive Must be a token! + */ + switch (*where) { + case ':': + tokp->kind = TOK_COLON; + where++; + break; + case ';': + tokp->kind = TOK_SEMICOLON; + where++; + break; + case ',': + tokp->kind = TOK_COMMA; + where++; + break; + case '=': + tokp->kind = TOK_EQUAL; + where++; + break; + case '*': + tokp->kind = TOK_STAR; + where++; + break; + case '[': + tokp->kind = TOK_LBRACKET; + where++; + break; + case ']': + tokp->kind = TOK_RBRACKET; + where++; + break; + case '{': + tokp->kind = TOK_LBRACE; + where++; + break; + case '}': + tokp->kind = TOK_RBRACE; + where++; + break; + case '(': + tokp->kind = TOK_LPAREN; + where++; + break; + case ')': + tokp->kind = TOK_RPAREN; + where++; + break; + case '<': + tokp->kind = TOK_LANGLE; + where++; + break; + case '>': + tokp->kind = TOK_RANGLE; + where++; + break; + + case '"': + tokp->kind = TOK_STRCONST; + findstrconst(&where, &tokp->str); + break; + case '\'': + tokp->kind = TOK_CHARCONST; + findchrconst(&where, &tokp->str); + break; + + case '-': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + tokp->kind = TOK_IDENT; + findconst(&where, &tokp->str); + break; + + default: + if (!(isalpha(*where) || *where == '_')) { + char buf[100]; + char *p; + + s_print(buf, "illegal character in file: "); + p = buf + strlen(buf); + if (isprint(*where)) { + s_print(p, "%c", *where); + } else { + s_print(p, "%d", *where); + } + error(buf); + } + findkind(&where, tokp); + break; + } +} + +static void +unget_token(tokp) + token *tokp; +{ + lasttok = *tokp; + pushed = 1; +} + +static void +findstrconst(str, val) + char **str; + char **val; +{ + char *p; + int size; + + p = *str; + do { + p++; + } while (*p && *p != '"'); + if (*p == 0) { + error("unterminated string constant"); + } + p++; + size = p - *str; + *val = alloc(size + 1); + (void) strncpy(*val, *str, size); + (*val)[size] = 0; + *str = p; +} + +static void +findchrconst(str, val) + char **str; + char **val; +{ + char *p; + int size; + + p = *str; + do { + p++; + } while (*p && *p != '\''); + if (*p == 0) { + error("unterminated string constant"); + } + p++; + size = p - *str; + if (size != 3) { + error("empty char string"); + } + *val = alloc(size + 1); + (void) strncpy(*val, *str, size); + (*val)[size] = 0; + *str = p; +} + +static void +findconst(str, val) + char **str; + char **val; +{ + char *p; + int size; + + p = *str; + if (*p == '0' && *(p + 1) == 'x') { + p++; + do { + p++; + } while (isxdigit(*p)); + } else { + do { + p++; + } while (isdigit(*p)); + } + size = p - *str; + *val = alloc(size + 1); + (void) strncpy(*val, *str, size); + (*val)[size] = 0; + *str = p; +} + +static token symbols[] = { + {TOK_CONST, "const"}, + {TOK_UNION, "union"}, + {TOK_SWITCH, "switch"}, + {TOK_CASE, "case"}, + {TOK_DEFAULT, "default"}, + {TOK_STRUCT, "struct"}, + {TOK_TYPEDEF, "typedef"}, + {TOK_ENUM, "enum"}, + {TOK_OPAQUE, "opaque"}, + {TOK_BOOL, "bool"}, + {TOK_VOID, "void"}, + {TOK_CHAR, "char"}, + {TOK_INT, "int"}, + {TOK_UNSIGNED, "unsigned"}, + {TOK_SHORT, "short"}, + {TOK_LONG, "long"}, + {TOK_HYPER, "hyper"}, + {TOK_FLOAT, "float"}, + {TOK_DOUBLE, "double"}, + {TOK_QUAD, "quadruple"}, + {TOK_STRING, "string"}, + {TOK_PROGRAM, "program"}, + {TOK_VERSION, "version"}, + {TOK_EOF, "??????"}, +}; + +static void +findkind(mark, tokp) + char **mark; + token *tokp; +{ + int len; + token *s; + char *str; + + str = *mark; + for (s = symbols; s->kind != TOK_EOF; s++) { + len = strlen(s->str); + if (strncmp(str, s->str, len) == 0) { + if (!isalnum(str[len]) && str[len] != '_') { + tokp->kind = s->kind; + tokp->str = s->str; + *mark = str + len; + return; + } + } + } + tokp->kind = TOK_IDENT; + for (len = 0; isalnum(str[len]) || str[len] == '_'; len++); + tokp->str = alloc(len + 1); + (void) strncpy(tokp->str, str, len); + tokp->str[len] = 0; + *mark = str + len; +} + +static int +cppline(line) + char *line; +{ + return (line == curline && *line == '#'); +} + +static int +directive(line) + char *line; +{ + return (line == curline && *line == '%'); +} + +static void +printdirective(line) + char *line; +{ + f_print(fout, "%s", line + 1); +} + +static void +docppline(line, lineno, fname) + char *line; + int *lineno; + char **fname; +{ + char *file; + int num; + char *p; + + line++; + while (isspace(*line)) { + line++; + } + num = atoi(line); + while (isdigit(*line)) { + line++; + } + while (isspace(*line)) { + line++; + } + if (*line != '"') { + error("preprocessor error"); + } + line++; + p = file = alloc(strlen(line) + 1); + while (*line && *line != '"') { + *p++ = *line++; + } + if (*line == 0) { + error("preprocessor error"); + } + *p = 0; + if (*file == 0) { + *fname = NULL; + } else { + *fname = file; + } + *lineno = num - 1; +} diff --git a/developer_cmds/rpcgen/rpc_scan.h b/developer_cmds/rpcgen/rpc_scan.h new file mode 100644 index 0000000..e4c57c8 --- /dev/null +++ b/developer_cmds/rpcgen/rpc_scan.h @@ -0,0 +1,104 @@ +/* $NetBSD: rpc_scan.h,v 1.4 1997/10/11 21:01:50 christos Exp $ */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user or with the express written consent of + * Sun Microsystems, Inc. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* @(#)rpc_scan.h 1.3 90/08/29 (C) 1987 SMI */ + +/* + * rpc_scan.h, Definitions for the RPCL scanner + */ + +/* + * kinds of tokens + */ +enum tok_kind { + TOK_IDENT, + TOK_CHARCONST, + TOK_STRCONST, + TOK_LPAREN, + TOK_RPAREN, + TOK_LBRACE, + TOK_RBRACE, + TOK_LBRACKET, + TOK_RBRACKET, + TOK_LANGLE, + TOK_RANGLE, + TOK_STAR, + TOK_COMMA, + TOK_EQUAL, + TOK_COLON, + TOK_SEMICOLON, + TOK_CONST, + TOK_STRUCT, + TOK_UNION, + TOK_SWITCH, + TOK_CASE, + TOK_DEFAULT, + TOK_ENUM, + TOK_TYPEDEF, + TOK_INT, + TOK_SHORT, + TOK_LONG, + TOK_HYPER, + TOK_UNSIGNED, + TOK_FLOAT, + TOK_DOUBLE, + TOK_QUAD, + TOK_OPAQUE, + TOK_CHAR, + TOK_STRING, + TOK_BOOL, + TOK_VOID, + TOK_PROGRAM, + TOK_VERSION, + TOK_EOF +}; +typedef enum tok_kind tok_kind; + +/* + * a token + */ +struct token { + tok_kind kind; + char *str; +}; +typedef struct token token; + + +/* + * routine interface + */ +void scan __P((tok_kind, token *)); +void scan2 __P((tok_kind, tok_kind, token *)); +void scan3 __P((tok_kind, tok_kind, tok_kind, token *)); +void scan_num __P((token *)); +void peek __P((token *)); +int peekscan __P((tok_kind, token *)); +void get_token __P((token *)); diff --git a/developer_cmds/rpcgen/rpc_svcout.c b/developer_cmds/rpcgen/rpc_svcout.c new file mode 100644 index 0000000..cb0ed46 --- /dev/null +++ b/developer_cmds/rpcgen/rpc_svcout.c @@ -0,0 +1,980 @@ +/* $NetBSD: rpc_svcout.c,v 1.10 1997/10/18 10:54:07 lukem Exp $ */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user or with the express written consent of + * Sun Microsystems, Inc. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)rpc_svcout.c 1.29 89/03/30 (C) 1987 SMI"; +#else +__RCSID("$NetBSD: rpc_svcout.c,v 1.10 1997/10/18 10:54:07 lukem Exp $"); +#endif +#endif + +/* + * rpc_svcout.c, Server-skeleton outputter for the RPC protocol compiler + */ +#include +#include +#include "rpc_scan.h" +#include "rpc_parse.h" +#include "rpc_util.h" + +static char RQSTP[] = "rqstp"; +static char TRANSP[] = "transp"; +static char ARG[] = "argument"; +static char RESULT[] = "result"; +static char ROUTINE[] = "local"; + +static void p_xdrfunc __P((char *, char *)); +static void internal_proctype __P((proc_list *)); +static void write_real_program __P((definition *)); +static void write_program __P((definition *, char *)); +static void printerr __P((char *, char *)); +static void printif __P((char *, char *, char *, char *)); +static void write_inetmost __P((char *)); +static void print_return __P((char *)); +static void print_pmapunset __P((char *)); +static void print_err_message __P((char *)); +static void write_timeout_func __P((void)); +static void write_caller_func __P((void)); +static void write_pm_most __P((char *, int)); +static void write_rpc_svc_fg __P((char *, char *)); +static void open_log_file __P((char *, char *)); + +char _errbuf[256]; /* For all messages */ + +static void +p_xdrfunc(rname, typename) + char *rname; + char *typename; +{ + if (Cflag) + f_print(fout, "\t\txdr_%s = (xdrproc_t) xdr_%s;\n", rname, + stringfix(typename)); + else + f_print(fout, "\t\txdr_%s = xdr_%s;\n", rname, stringfix(typename)); +} + +static void +internal_proctype(plist) + proc_list *plist; +{ + f_print(fout, "static "); + ptype(plist->res_prefix, plist->res_type, 1); + f_print(fout, "*"); +} + + +/* + * write most of the service, that is, everything but the registrations. + */ +void +write_most(infile, netflag, nomain) + char *infile; /* our name */ + int netflag; + int nomain; +{ + if (inetdflag || pmflag) { + char *var_type; + var_type = (nomain ? "extern" : "static"); + f_print(fout, "%s int _rpcpmstart;", var_type); + f_print(fout, "\t\t/* Started by a port monitor ? */\n"); + f_print(fout, "%s int _rpcfdtype;", var_type); + f_print(fout, "\t\t/* Whether Stream or Datagram ? */\n"); + if (timerflag) { + f_print(fout, "%s int _rpcsvcdirty;", var_type); + f_print(fout, "\t/* Still serving ? */\n"); + } + write_svc_aux(nomain); + } + /* write out dispatcher and stubs */ + write_programs(nomain ? (char *) NULL : "static"); + + if (nomain) + return; + + f_print(fout, "\n\n"); + if (Cflag) + f_print(fout, "int main( int argc, char* argv[] );\n"); + f_print(fout, "\nint\n"); + if (Cflag) + f_print(fout, "main( int argc, char* argv[] )\n"); + else + f_print(fout, "main(argc, argv)\nint argc;\nchar *argv[];\n"); + f_print(fout, "{\n"); + if (inetdflag) { + write_inetmost(infile); /* Includes call to write_rpc_svc_fg() */ + } else { + if (tirpcflag) { + if (netflag) { + f_print(fout, "\tSVCXPRT *%s;\n", TRANSP); + f_print(fout, "\tstruct netconfig *nconf = NULL;\n"); + } + f_print(fout, "\tpid_t pid;\n"); + f_print(fout, "\tint i;\n"); + f_print(fout, "\tchar mname[FMNAMESZ + 1];\n\n"); + write_pm_most(infile, netflag); + f_print(fout, "\telse {\n"); + write_rpc_svc_fg(infile, "\t\t"); + f_print(fout, "\t}\n"); + } else { + f_print(fout, "\tSVCXPRT *%s;\n", TRANSP); + f_print(fout, "\n"); + print_pmapunset("\t"); + } + } + + if (logflag && !inetdflag) { + open_log_file(infile, "\t"); + } +} +/* + * write a registration for the given transport + */ +void +write_netid_register(transp) + char *transp; +{ + list *l; + definition *def; + version_list *vp; + char *sp; + char tmpbuf[32]; + + sp = ""; + f_print(fout, "\n"); + f_print(fout, "%s\tnconf = getnetconfigent(\"%s\");\n", sp, transp); + f_print(fout, "%s\tif (nconf == NULL) {\n", sp); + (void) sprintf(_errbuf, "cannot find %s netid.", transp); + sprintf(tmpbuf, "%s\t\t", sp); + print_err_message(tmpbuf); + f_print(fout, "%s\t\texit(1);\n", sp); + f_print(fout, "%s\t}\n", sp); + f_print(fout, "%s\t%s = svc_tli_create(RPC_ANYFD, nconf, 0, 0, 0);\n", + sp, TRANSP); + f_print(fout, "%s\tif (%s == NULL) {\n", sp, TRANSP); + (void) sprintf(_errbuf, "cannot create %s service.", transp); + print_err_message(tmpbuf); + f_print(fout, "%s\t\texit(1);\n", sp); + f_print(fout, "%s\t}\n", sp); + + for (l = defined; l != NULL; l = l->next) { + def = (definition *) l->val; + if (def->def_kind != DEF_PROGRAM) { + continue; + } + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) { + f_print(fout, + "%s\t(void) rpcb_unset(%s, %s, nconf);\n", + sp, def->def_name, vp->vers_name); + f_print(fout, + "%s\tif (!svc_reg(%s, %s, %s, ", + sp, TRANSP, def->def_name, vp->vers_name); + pvname(def->def_name, vp->vers_num); + f_print(fout, ", nconf)) {\n"); + (void) sprintf(_errbuf, "unable to register (%s, %s, %s).", + def->def_name, vp->vers_name, transp); + print_err_message(tmpbuf); + f_print(fout, "%s\t\texit(1);\n", sp); + f_print(fout, "%s\t}\n", sp); + } + } + f_print(fout, "%s\tfreenetconfigent(nconf);\n", sp); +} +/* + * write a registration for the given transport for TLI + */ +void +write_nettype_register(transp) + char *transp; +{ + list *l; + definition *def; + version_list *vp; + + for (l = defined; l != NULL; l = l->next) { + def = (definition *) l->val; + if (def->def_kind != DEF_PROGRAM) { + continue; + } + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) { + f_print(fout, "\tif (!svc_create("); + pvname(def->def_name, vp->vers_num); + f_print(fout, ", %s, %s, \"%s\")) {\n ", + def->def_name, vp->vers_name, transp); + (void) sprintf(_errbuf, + "unable to create (%s, %s) for %s.", + def->def_name, vp->vers_name, transp); + print_err_message("\t\t"); + f_print(fout, "\t\texit(1);\n"); + f_print(fout, "\t}\n"); + } + } +} +/* + * write the rest of the service + */ +void +write_rest() +{ + f_print(fout, "\n"); + if (inetdflag) { + f_print(fout, "\tif (%s == (SVCXPRT *)NULL) {\n", TRANSP); + (void) sprintf(_errbuf, "could not create a handle"); + print_err_message("\t\t"); + f_print(fout, "\t\texit(1);\n"); + f_print(fout, "\t}\n"); + if (timerflag) { + f_print(fout, "\tif (_rpcpmstart) {\n"); + f_print(fout, + "\t\t(void) signal(SIGALRM, %s closedown);\n", + Cflag ? "(SIG_PF)" : "(void(*)())"); + f_print(fout, "\t\t(void) alarm(_RPCSVC_CLOSEDOWN);\n"); + f_print(fout, "\t}\n"); + } + } + f_print(fout, "\tsvc_run();\n"); + (void) sprintf(_errbuf, "svc_run returned"); + print_err_message("\t"); + f_print(fout, "\texit(1);\n"); + f_print(fout, "\t/* NOTREACHED */\n"); + f_print(fout, "}\n"); +} + +void +write_programs(storage) + char *storage; +{ + list *l; + definition *def; + + /* write out stubs for procedure definitions */ + for (l = defined; l != NULL; l = l->next) { + def = (definition *) l->val; + if (def->def_kind == DEF_PROGRAM) { + write_real_program(def); + } + } + + /* write out dispatcher for each program */ + for (l = defined; l != NULL; l = l->next) { + def = (definition *) l->val; + if (def->def_kind == DEF_PROGRAM) { + write_program(def, storage); + } + } + + +} +/* write out definition of internal function (e.g. _printmsg_1(...)) + which calls server's defintion of actual function (e.g. printmsg_1(...)). + Unpacks single user argument of printmsg_1 to call-by-value format + expected by printmsg_1. */ +static void +write_real_program(def) + definition *def; +{ + version_list *vp; + proc_list *proc; + decl_list *l; + + if (!newstyle) + return; /* not needed for old style */ + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) { + for (proc = vp->procs; proc != NULL; proc = proc->next) { + f_print(fout, "\n"); + internal_proctype(proc); + f_print(fout, "\n_"); + pvname(proc->proc_name, vp->vers_num); + if (Cflag) { + f_print(fout, "("); + /* arg name */ + if (proc->arg_num > 1) + f_print(fout, "%s", proc->args.argname); + else + ptype(proc->args.decls->decl.prefix, + proc->args.decls->decl.type, 0); + f_print(fout, " *argp, struct svc_req *%s)\n", + RQSTP); + } else { + f_print(fout, "(argp, %s)\n", RQSTP); + /* arg name */ + if (proc->arg_num > 1) + f_print(fout, "\t%s *argp;\n", proc->args.argname); + else { + f_print(fout, "\t"); + ptype(proc->args.decls->decl.prefix, + proc->args.decls->decl.type, 0); + f_print(fout, " *argp;\n"); + } + f_print(fout, " struct svc_req *%s;\n", RQSTP); + } + + f_print(fout, "{\n"); + f_print(fout, "\treturn("); + pvname_svc(proc->proc_name, vp->vers_num); + f_print(fout, "("); + if (proc->arg_num < 2) { /* single argument */ + if (!streq(proc->args.decls->decl.type, "void")) + f_print(fout, "*argp, "); /* non-void */ + } else { + for (l = proc->args.decls; l != NULL; l = l->next) + f_print(fout, "argp->%s, ", l->decl.name); + } + f_print(fout, "%s));\n}\n", RQSTP); + } + } +} + +static void +write_program(def, storage) + definition *def; + char *storage; +{ + version_list *vp; + proc_list *proc; + int filled; + + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) { + if (Cflag) { + f_print(fout, "\n"); + if (storage != NULL) { + f_print(fout, "%s ", storage); + } + f_print(fout, "void "); + pvname(def->def_name, vp->vers_num); + f_print(fout, "(struct svc_req *%s, ", RQSTP); + f_print(fout, "SVCXPRT *%s);\n", TRANSP); + } + f_print(fout, "\n"); + if (storage != NULL) { + f_print(fout, "%s ", storage); + } + f_print(fout, "void\n"); + pvname(def->def_name, vp->vers_num); + + if (Cflag) { + f_print(fout, "(struct svc_req *%s, ", RQSTP); + f_print(fout, "SVCXPRT *%s)\n", TRANSP); + } else { + f_print(fout, "(%s, %s)\n", RQSTP, TRANSP); + f_print(fout, " struct svc_req *%s;\n", RQSTP); + f_print(fout, " SVCXPRT *%s;\n", TRANSP); + } + + f_print(fout, "{\n"); + + filled = 0; + f_print(fout, "\tunion {\n"); + for (proc = vp->procs; proc != NULL; proc = proc->next) { + if (proc->arg_num < 2) { /* single argument */ + if (streq(proc->args.decls->decl.type, + "void")) { + continue; + } + filled = 1; + f_print(fout, "\t\t"); + ptype(proc->args.decls->decl.prefix, + proc->args.decls->decl.type, 0); + pvname(proc->proc_name, vp->vers_num); + f_print(fout, "_arg;\n"); + + } else { + filled = 1; + f_print(fout, "\t\t%s", proc->args.argname); + f_print(fout, " "); + pvname(proc->proc_name, vp->vers_num); + f_print(fout, "_arg;\n"); + } + } + if (!filled) { + f_print(fout, "\t\tint fill;\n"); + } + f_print(fout, "\t} %s;\n", ARG); + f_print(fout, "\tchar *%s;\n", RESULT); + + if (Cflag) { + f_print(fout, "\txdrproc_t xdr_%s, xdr_%s;\n", ARG, RESULT); + f_print(fout, + "\tchar *(*%s)(char *, struct svc_req *);\n", + ROUTINE); + } else { + f_print(fout, "\tbool_t (*xdr_%s)(), (*xdr_%s)();\n", ARG, RESULT); + f_print(fout, "\tchar *(*%s)();\n", ROUTINE); + } + + f_print(fout, "\n"); + + if (callerflag) + f_print(fout, "\tcaller = transp;\n"); /* EVAS */ + if (timerflag) + f_print(fout, "\t_rpcsvcdirty = 1;\n"); + f_print(fout, "\tswitch (%s->rq_proc) {\n", RQSTP); + if (!nullproc(vp->procs)) { + f_print(fout, "\tcase NULLPROC:\n"); + f_print(fout, + "\t\t(void) svc_sendreply(%s, (xdrproc_t) xdr_void, (char *)NULL);\n", + TRANSP); + print_return("\t\t"); + f_print(fout, "\n"); + } + for (proc = vp->procs; proc != NULL; proc = proc->next) { + f_print(fout, "\tcase %s:\n", proc->proc_name); + if (proc->arg_num < 2) { /* single argument */ + p_xdrfunc(ARG, proc->args.decls->decl.type); + } else { + p_xdrfunc(ARG, proc->args.argname); + } + p_xdrfunc(RESULT, proc->res_type); + if (Cflag) + f_print(fout, + "\t\t%s = (char *(*)(char *, struct svc_req *)) ", + ROUTINE); + else + f_print(fout, "\t\t%s = (char *(*)()) ", ROUTINE); + + if (newstyle) { /* new style: calls internal routine */ + f_print(fout, "_"); + } + if (!newstyle) + pvname_svc(proc->proc_name, vp->vers_num); + else + pvname(proc->proc_name, vp->vers_num); + f_print(fout, ";\n"); + f_print(fout, "\t\tbreak;\n\n"); + } + f_print(fout, "\tdefault:\n"); + printerr("noproc", TRANSP); + print_return("\t\t"); + f_print(fout, "\t}\n"); + + f_print(fout, "\t(void) memset((char *)&%s, 0, sizeof (%s));\n", ARG, ARG); + printif("getargs", TRANSP, "(caddr_t) &", ARG); + printerr("decode", TRANSP); + print_return("\t\t"); + f_print(fout, "\t}\n"); + + if (Cflag) + f_print(fout, "\t%s = (*%s)((char *)&%s, %s);\n", + RESULT, ROUTINE, ARG, RQSTP); + else + f_print(fout, "\t%s = (*%s)(&%s, %s);\n", + RESULT, ROUTINE, ARG, RQSTP); + f_print(fout, + "\tif (%s != NULL && !svc_sendreply(%s, (xdrproc_t) xdr_%s, %s)) {\n", + RESULT, TRANSP, RESULT, RESULT); + printerr("systemerr", TRANSP); + f_print(fout, "\t}\n"); + + printif("freeargs", TRANSP, "(caddr_t) &", ARG); + (void) sprintf(_errbuf, "unable to free arguments"); + print_err_message("\t\t"); + f_print(fout, "\t\texit(1);\n"); + f_print(fout, "\t}\n"); + print_return("\t"); + f_print(fout, "}\n"); + } +} + +static void +printerr(err, transp) + char *err; + char *transp; +{ + f_print(fout, "\t\tsvcerr_%s(%s);\n", err, transp); +} + +static void +printif(proc, transp, prefix, arg) + char *proc; + char *transp; + char *prefix; + char *arg; +{ + f_print(fout, "\tif (!svc_%s(%s, xdr_%s, %s%s)) {\n", + proc, transp, arg, prefix, arg); +} + +int +nullproc(proc) + proc_list *proc; +{ + for (; proc != NULL; proc = proc->next) { + if (streq(proc->proc_num, "0")) { + return (1); + } + } + return (0); +} + +static void +write_inetmost(infile) + char *infile; +{ + f_print(fout, "\tSVCXPRT *%s = NULL;\n", TRANSP); + f_print(fout, "\tint sock;\n"); + f_print(fout, "\tint proto = 0;\n"); + f_print(fout, "\tstruct sockaddr_in saddr;\n"); + f_print(fout, "\tint asize = sizeof (saddr);\n"); + f_print(fout, "\n"); + f_print(fout, + "\tif (getsockname(0, (struct sockaddr *)&saddr, &asize) == 0) {\n"); + f_print(fout, "\t\tint ssize = sizeof (int);\n\n"); + f_print(fout, "\t\tif (saddr.sin_family != AF_INET)\n"); + f_print(fout, "\t\t\texit(1);\n"); + f_print(fout, "\t\tif (getsockopt(0, SOL_SOCKET, SO_TYPE,\n"); + f_print(fout, "\t\t\t\t(char *)&_rpcfdtype, &ssize) == -1)\n"); + f_print(fout, "\t\t\texit(1);\n"); + f_print(fout, "\t\tsock = 0;\n"); + f_print(fout, "\t\t_rpcpmstart = 1;\n"); + f_print(fout, "\t\tproto = 0;\n"); + open_log_file(infile, "\t\t"); + f_print(fout, "\t} else {\n"); + write_rpc_svc_fg(infile, "\t\t"); + f_print(fout, "\t\tsock = RPC_ANYSOCK;\n"); + print_pmapunset("\t\t"); + f_print(fout, "\t}\n"); +} + +static void +print_return(space) + char *space; +{ + if (exitnow) + f_print(fout, "%sexit(0);\n", space); + else { + if (timerflag) + f_print(fout, "%s_rpcsvcdirty = 0;\n", space); + f_print(fout, "%sreturn;\n", space); + } +} + +static void +print_pmapunset(space) + char *space; +{ + list *l; + definition *def; + version_list *vp; + + for (l = defined; l != NULL; l = l->next) { + def = (definition *) l->val; + if (def->def_kind == DEF_PROGRAM) { + for (vp = def->def.pr.versions; vp != NULL; + vp = vp->next) { + f_print(fout, "%s(void) pmap_unset(%s, %s);\n", + space, def->def_name, vp->vers_name); + } + } + } +} + +static void +print_err_message(space) + char *space; +{ + if (logflag) + f_print(fout, "%ssyslog(LOG_ERR, \"%%s\", \"%s\");\n", space, _errbuf); + else + if (inetdflag || pmflag) + f_print(fout, "%s_msgout(\"%s\");\n", space, _errbuf); + else + f_print(fout, "%sfprintf(stderr, \"%%s\", \"%s\");\n", space, _errbuf); +} +/* + * Write the server auxiliary function ( _msgout, timeout) + */ +void +write_svc_aux(nomain) + int nomain; +{ + if (!logflag) + write_msg_out(); + if (!nomain) + write_timeout_func(); + if (callerflag) /* EVAS */ + write_caller_func(); /* EVAS */ +} +/* + * Write the _msgout function + */ +void +write_msg_out() +{ + f_print(fout, "\n"); + f_print(fout, "static\n"); + if (!Cflag) { + f_print(fout, "void _msgout(msg)\n"); + f_print(fout, "\tchar *msg;\n"); + } else { + f_print(fout, "void _msgout(char* msg)\n"); + } + f_print(fout, "{\n"); + f_print(fout, "#ifdef RPC_SVC_FG\n"); + if (inetdflag || pmflag) + f_print(fout, "\tif (_rpcpmstart)\n"); + f_print(fout, "\t\tsyslog(LOG_ERR, \"%%s\", msg);\n"); + f_print(fout, "\telse\n"); + f_print(fout, "\t\t(void) fprintf(stderr, \"%%s\\n\", msg);\n"); + f_print(fout, "#else\n"); + f_print(fout, "\tsyslog(LOG_ERR, \"%%s\", msg);\n"); + f_print(fout, "#endif\n"); + f_print(fout, "}\n"); +} +/* + * Write the timeout function + */ +static void +write_timeout_func() +{ + if (!timerflag) + return; + if (Cflag) { + f_print(fout, "\n"); + f_print(fout, "static void closedown(void);\n"); + } + f_print(fout, "\n"); + f_print(fout, "static void\n"); + f_print(fout, "closedown()\n"); + f_print(fout, "{\n"); + f_print(fout, "\tif (_rpcsvcdirty == 0) {\n"); + f_print(fout, "\t\textern fd_set svc_fdset;\n"); + f_print(fout, "\t\tstatic int size;\n"); + f_print(fout, "\t\tint i, openfd;\n"); + if (tirpcflag && pmflag) { + f_print(fout, "\t\tstruct t_info tinfo;\n\n"); + f_print(fout, "\t\tif (!t_getinfo(0, &tinfo) && (tinfo.servtype == T_CLTS))\n"); + } else { + f_print(fout, "\n\t\tif (_rpcfdtype == SOCK_DGRAM)\n"); + } + f_print(fout, "\t\t\texit(0);\n"); + f_print(fout, "\t\tif (size == 0) {\n"); + if (tirpcflag) { + f_print(fout, "\t\t\tstruct rlimit rl;\n\n"); + f_print(fout, "\t\t\trl.rlim_max = 0;\n"); + f_print(fout, "\t\t\tgetrlimit(RLIMIT_NOFILE, &rl);\n"); + f_print(fout, "\t\t\tif ((size = rl.rlim_max) == 0)\n"); + f_print(fout, "\t\t\t\treturn;\n"); + } else { + f_print(fout, "\t\t\tsize = getdtablesize();\n"); + } + f_print(fout, "\t\t}\n"); + f_print(fout, "\t\tfor (i = 0, openfd = 0; i < size && openfd < 2; i++)\n"); + f_print(fout, "\t\t\tif (FD_ISSET(i, &svc_fdset))\n"); + f_print(fout, "\t\t\t\topenfd++;\n"); + f_print(fout, "\t\tif (openfd <= (_rpcpmstart?0:1))\n"); + f_print(fout, "\t\t\texit(0);\n"); + f_print(fout, "\t}\n"); + f_print(fout, "\t(void) alarm(_RPCSVC_CLOSEDOWN);\n"); + f_print(fout, "}\n"); +} + +static void +write_caller_func() +{ /* EVAS */ +#define P(s) f_print(fout, s); + + P("\n"); + P("char *svc_caller()\n"); + P("{\n"); + P(" struct sockaddr_in actual;\n"); + P(" struct hostent *hp;\n"); + P(" static struct in_addr prev;\n"); + P(" static char cname[128];\n\n"); + + P(" actual = *svc_getcaller(caller);\n\n"); + + P(" if (memcmp((char *)&actual.sin_addr, (char *)&prev,\n"); + P(" sizeof(struct in_addr)) == 0)\n"); + P(" return (cname);\n\n"); + + P(" prev = actual.sin_addr;\n\n"); + + P(" hp = gethostbyaddr((char *) &actual.sin_addr, sizeof(actual.sin_addr), AF_INET);\n"); + P(" if (hp == NULL) { /* dummy one up */\n"); + P(" extern char *inet_ntoa();\n"); + P(" strcpy(cname, inet_ntoa(actual.sin_addr));\n"); + P(" } else {\n"); + P(" strcpy(cname, hp->h_name);\n"); + P(" }\n\n"); + + P(" return (cname);\n"); + P("}\n"); + +#undef P +} +/* + * Write the most of port monitor support + */ +static void +write_pm_most(infile, netflag) + char *infile; + int netflag; +{ + list *l; + definition *def; + version_list *vp; + + f_print(fout, "\tif (!ioctl(0, I_LOOK, mname) &&\n"); + f_print(fout, "\t\t(!strcmp(mname, \"sockmod\") ||"); + f_print(fout, " !strcmp(mname, \"timod\"))) {\n"); + f_print(fout, "\t\tchar *netid;\n"); + if (!netflag) { /* Not included by -n option */ + f_print(fout, "\t\tstruct netconfig *nconf = NULL;\n"); + f_print(fout, "\t\tSVCXPRT *%s;\n", TRANSP); + } + if (timerflag) + f_print(fout, "\t\tint pmclose;\n"); +/* not necessary, defined in /usr/include/stdlib */ +/* f_print(fout, "\t\textern char *getenv();\n");*/ + f_print(fout, "\n"); + f_print(fout, "\t\t_rpcpmstart = 1;\n"); + if (logflag) + open_log_file(infile, "\t\t"); + f_print(fout, "\t\tif ((netid = getenv(\"NLSPROVIDER\")) == NULL) {\n"); + sprintf(_errbuf, "cannot get transport name"); + print_err_message("\t\t\t"); + f_print(fout, "\t\t} else if ((nconf = getnetconfigent(netid)) == NULL) {\n"); + sprintf(_errbuf, "cannot get transport info"); + print_err_message("\t\t\t"); + f_print(fout, "\t\t}\n"); + /* + * A kludgy support for inetd services. Inetd only works with + * sockmod, and RPC works only with timod, hence all this jugglery + */ + f_print(fout, "\t\tif (strcmp(mname, \"sockmod\") == 0) {\n"); + f_print(fout, "\t\t\tif (ioctl(0, I_POP, 0) || ioctl(0, I_PUSH, \"timod\")) {\n"); + sprintf(_errbuf, "could not get the right module"); + print_err_message("\t\t\t\t"); + f_print(fout, "\t\t\t\texit(1);\n"); + f_print(fout, "\t\t\t}\n"); + f_print(fout, "\t\t}\n"); + if (timerflag) + f_print(fout, "\t\tpmclose = (t_getstate(0) != T_DATAXFER);\n"); + f_print(fout, "\t\tif ((%s = svc_tli_create(0, nconf, NULL, 0, 0)) == NULL) {\n", + TRANSP); + sprintf(_errbuf, "cannot create server handle"); + print_err_message("\t\t\t"); + f_print(fout, "\t\t\texit(1);\n"); + f_print(fout, "\t\t}\n"); + f_print(fout, "\t\tif (nconf)\n"); + f_print(fout, "\t\t\tfreenetconfigent(nconf);\n"); + for (l = defined; l != NULL; l = l->next) { + def = (definition *) l->val; + if (def->def_kind != DEF_PROGRAM) { + continue; + } + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) { + f_print(fout, + "\t\tif (!svc_reg(%s, %s, %s, ", + TRANSP, def->def_name, vp->vers_name); + pvname(def->def_name, vp->vers_num); + f_print(fout, ", 0)) {\n"); + (void) sprintf(_errbuf, "unable to register (%s, %s).", + def->def_name, vp->vers_name); + print_err_message("\t\t\t"); + f_print(fout, "\t\t\texit(1);\n"); + f_print(fout, "\t\t}\n"); + } + } + if (timerflag) { + f_print(fout, "\t\tif (pmclose) {\n"); + f_print(fout, "\t\t\t(void) signal(SIGALRM, %s closedown);\n", + Cflag ? "(SIG_PF)" : "(void(*)())"); + f_print(fout, "\t\t\t(void) alarm(_RPCSVC_CLOSEDOWN);\n"); + f_print(fout, "\t\t}\n"); + } + f_print(fout, "\t\tsvc_run();\n"); + f_print(fout, "\t\texit(1);\n"); + f_print(fout, "\t\t/* NOTREACHED */\n"); + f_print(fout, "\t}\n"); +} +/* + * Support for backgrounding the server if self started. + */ +static void +write_rpc_svc_fg(infile, sp) + char *infile; + char *sp; +{ + f_print(fout, "#ifndef RPC_SVC_FG\n"); + f_print(fout, "%sint size;\n", sp); + if (tirpcflag) + f_print(fout, "%sstruct rlimit rl;\n", sp); + if (inetdflag) + f_print(fout, "%sint pid, i;\n\n", sp); + f_print(fout, "%spid = fork();\n", sp); + f_print(fout, "%sif (pid < 0) {\n", sp); + f_print(fout, "%s\tperror(\"cannot fork\");\n", sp); + f_print(fout, "%s\texit(1);\n", sp); + f_print(fout, "%s}\n", sp); + f_print(fout, "%sif (pid)\n", sp); + f_print(fout, "%s\texit(0);\n", sp); + /* get number of file descriptors */ + if (tirpcflag) { + f_print(fout, "%srl.rlim_max = 0;\n", sp); + f_print(fout, "%sgetrlimit(RLIMIT_NOFILE, &rl);\n", sp); + f_print(fout, "%sif ((size = rl.rlim_max) == 0)\n", sp); + f_print(fout, "%s\texit(1);\n", sp); + } else { + f_print(fout, "%ssize = getdtablesize();\n", sp); + } + + f_print(fout, "%sfor (i = 0; i < size; i++)\n", sp); + f_print(fout, "%s\t(void) close(i);\n", sp); + /* Redirect stderr and stdout to console */ + f_print(fout, "%si = open(\"/dev/console\", 2);\n", sp); + f_print(fout, "%s(void) dup2(i, 1);\n", sp); + f_print(fout, "%s(void) dup2(i, 2);\n", sp); + /* This removes control of the controlling terminal */ + if (tirpcflag) + f_print(fout, "%ssetsid();\n", sp); + else { + f_print(fout, "%si = open(\"/dev/tty\", 2);\n", sp); + f_print(fout, "%sif (i >= 0) {\n", sp); + f_print(fout, "%s\t(void) ioctl(i, TIOCNOTTY, (char *)NULL);\n", sp);; + f_print(fout, "%s\t(void) close(i);\n", sp); + f_print(fout, "%s}\n", sp); + } + if (!logflag) + open_log_file(infile, sp); + f_print(fout, "#endif\n"); + if (logflag) + open_log_file(infile, sp); +} + +static void +open_log_file(infile, sp) + char *infile; + char *sp; +{ + char *s, *p; + + s = strrchr(infile, '.'); + if (s) + *s = '\0'; + p = strrchr(infile, '/'); + if (p) + p++; + else + p = infile; + f_print(fout, "%sopenlog(\"%s\", LOG_PID, LOG_DAEMON);\n", sp, p); + if (s) + *s = '.'; +} + +/* + * write a registration for the given transport for Inetd + */ +void +write_inetd_register(transp) + char *transp; +{ + list *l; + definition *def; + version_list *vp; + char *sp; + int isudp; + char tmpbuf[32]; + + if (inetdflag) + sp = "\t"; + else + sp = ""; + if (streq(transp, "udp")) + isudp = 1; + else + isudp = 0; + f_print(fout, "\n"); + if (inetdflag) { + f_print(fout, "\tif ((_rpcfdtype == 0) || (_rpcfdtype == %s)) {\n", + isudp ? "SOCK_DGRAM" : "SOCK_STREAM"); + } + if (inetdflag && streq(transp, "tcp")) { + f_print(fout, "%s\tif (_rpcpmstart)\n", sp); + + f_print(fout, "%s\t\t%s = svc%s_create(%s", + sp, TRANSP, "fd", inetdflag ? "sock" : "RPC_ANYSOCK"); + if (!isudp) + f_print(fout, ", 0, 0"); + f_print(fout, ");\n"); + + f_print(fout, "%s\telse\n", sp); + + f_print(fout, "%s\t\t%s = svc%s_create(%s", + sp, TRANSP, transp, inetdflag ? "sock" : "RPC_ANYSOCK"); + if (!isudp) + f_print(fout, ", 0, 0"); + f_print(fout, ");\n"); + + } else { + f_print(fout, "%s\t%s = svc%s_create(%s", + sp, TRANSP, transp, inetdflag ? "sock" : "RPC_ANYSOCK"); + if (!isudp) + f_print(fout, ", 0, 0"); + f_print(fout, ");\n"); + } + f_print(fout, "%s\tif (%s == NULL) {\n", sp, TRANSP); + (void) sprintf(_errbuf, "cannot create %s service.", transp); + (void) sprintf(tmpbuf, "%s\t\t", sp); + print_err_message(tmpbuf); + f_print(fout, "%s\t\texit(1);\n", sp); + f_print(fout, "%s\t}\n", sp); + + if (inetdflag) { + f_print(fout, "%s\tif (!_rpcpmstart)\n\t", sp); + f_print(fout, "%s\tproto = IPPROTO_%s;\n", + sp, isudp ? "UDP" : "TCP"); + } + for (l = defined; l != NULL; l = l->next) { + def = (definition *) l->val; + if (def->def_kind != DEF_PROGRAM) { + continue; + } + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) { + f_print(fout, "%s\tif (!svc_register(%s, %s, %s, ", + sp, TRANSP, def->def_name, vp->vers_name); + pvname(def->def_name, vp->vers_num); + if (inetdflag) + f_print(fout, ", proto)) {\n"); + else + f_print(fout, ", IPPROTO_%s)) {\n", + isudp ? "UDP" : "TCP"); + (void) sprintf(_errbuf, "unable to register (%s, %s, %s).", + def->def_name, vp->vers_name, transp); + print_err_message(tmpbuf); + f_print(fout, "%s\t\texit(1);\n", sp); + f_print(fout, "%s\t}\n", sp); + } + } + if (inetdflag) + f_print(fout, "\t}\n"); +} diff --git a/developer_cmds/rpcgen/rpc_tblout.c b/developer_cmds/rpcgen/rpc_tblout.c new file mode 100644 index 0000000..610dcd0 --- /dev/null +++ b/developer_cmds/rpcgen/rpc_tblout.c @@ -0,0 +1,179 @@ +/* $NetBSD: rpc_tblout.c,v 1.7 1997/10/18 10:54:11 lukem Exp $ */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user or with the express written consent of + * Sun Microsystems, Inc. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)rpc_tblout.c 1.4 89/02/22 (C) 1988 SMI"; +#else +__RCSID("$NetBSD: rpc_tblout.c,v 1.7 1997/10/18 10:54:11 lukem Exp $"); +#endif +#endif + +/* + * rpc_tblout.c, Dispatch table outputter for the RPC protocol compiler + */ +#include +#include +#include +#include "rpc_scan.h" +#include "rpc_parse.h" +#include "rpc_util.h" + +#define TABSIZE 8 +#define TABCOUNT 5 +#define TABSTOP (TABSIZE*TABCOUNT) + +static char tabstr[TABCOUNT + 1] = "\t\t\t\t\t"; + +static char tbl_hdr[] = "struct rpcgen_table %s_table[] = {\n"; +static char tbl_end[] = "};\n"; + +static char null_entry[] = "\t(char *(*)())0,\n\ + \t(xdrproc_t)xdr_void,\t\t0,\n\ + \t(xdrproc_t)xdr_void,\t\t0,\n"; + +static char tbl_nproc[] = "int %s_nproc =\n\tsizeof(%s_table)/sizeof(%s_table[0]);\n\n"; + +static void write_table __P((definition *)); +static void printit __P((char *, char *)); + +void +write_tables() +{ + list *l; + definition *def; + + f_print(fout, "\n"); + for (l = defined; l != NULL; l = l->next) { + def = (definition *) l->val; + if (def->def_kind == DEF_PROGRAM) { + write_table(def); + } + } +} + +static void +write_table(def) + definition *def; +{ + version_list *vp; + proc_list *proc; + int current; + int expected; + char progvers[100]; + int warning; + + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) { + warning = 0; + s_print(progvers, "%s_%s", + locase(def->def_name), vp->vers_num); + /* print the table header */ + f_print(fout, tbl_hdr, progvers); + + if (nullproc(vp->procs)) { + expected = 0; + } else { + expected = 1; + f_print(fout, "%s", null_entry); + } + for (proc = vp->procs; proc != NULL; proc = proc->next) { + if (expected != 0) + f_print(fout, "\n"); + current = atoi(proc->proc_num); + if (current != expected++) { + f_print(fout, + "/*\n * WARNING: table out of order\n */\n\n"); + if (warning == 0) { + f_print(stderr, + "WARNING %s table is out of order\n", + progvers); + warning = 1; + nonfatalerrors = 1; + } + expected = current + 1; + } + f_print(fout, "\t(char *(*)())RPCGEN_ACTION("); + + /* routine to invoke */ + if (!newstyle) + pvname_svc(proc->proc_name, vp->vers_num); + else { + if (newstyle) + f_print(fout, "_"); /* calls internal func */ + pvname(proc->proc_name, vp->vers_num); + } + f_print(fout, "),\n"); + + /* argument info */ + if (proc->arg_num > 1) + printit((char *) NULL, proc->args.argname); + else + /* do we have to do something special for + * newstyle */ + printit(proc->args.decls->decl.prefix, + proc->args.decls->decl.type); + /* result info */ + printit(proc->res_prefix, proc->res_type); + } + + /* print the table trailer */ + f_print(fout, "%s", tbl_end); + f_print(fout, tbl_nproc, progvers, progvers, progvers); + } +} + +static void +printit(prefix, type) + char *prefix; + char *type; +{ + int len; + int tabs; + + + len = fprintf(fout, "\txdr_%s,", stringfix(type)); + /* account for leading tab expansion */ + len += TABSIZE - 1; + /* round up to tabs required */ + tabs = (TABSTOP - len + TABSIZE - 1) / TABSIZE; + f_print(fout, "%s", &tabstr[TABCOUNT - tabs]); + + if (streq(type, "void")) { + f_print(fout, "0"); + } else { + f_print(fout, "sizeof ( "); + /* XXX: should "follow" be 1 ??? */ + ptype(prefix, type, 0); + f_print(fout, ")"); + } + f_print(fout, ",\n"); +} diff --git a/developer_cmds/rpcgen/rpc_util.c b/developer_cmds/rpcgen/rpc_util.c new file mode 100644 index 0000000..f51114c --- /dev/null +++ b/developer_cmds/rpcgen/rpc_util.c @@ -0,0 +1,513 @@ +/* $NetBSD: rpc_util.c,v 1.8 1997/10/18 10:54:14 lukem Exp $ */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user or with the express written consent of + * Sun Microsystems, Inc. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)rpc_util.c 1.11 89/02/22 (C) 1987 SMI"; +#else +__RCSID("$NetBSD: rpc_util.c,v 1.8 1997/10/18 10:54:14 lukem Exp $"); +#endif +#endif + +/* + * rpc_util.c, Utility routines for the RPC protocol compiler + */ +#include +#include +#include +#include +#include +#include "rpc_scan.h" +#include "rpc_parse.h" +#include "rpc_util.h" + +#define ARGEXT "argument" + +static void printwhere __P((void)); + +char curline[MAXLINESIZE]; /* current read line */ +char *where = curline; /* current point in line */ +int linenum = 0; /* current line number */ + +char *infilename; /* input filename */ + +#define NFILES 7 +char *outfiles[NFILES]; /* output file names */ +int nfiles; + +FILE *fout; /* file pointer of current output */ +FILE *fin; /* file pointer of current input */ + +list *defined; /* list of defined things */ + +static char *toktostr __P((tok_kind)); +static void printbuf __P((void)); +static void printwhere __P((void)); +static int findit __P((definition *, char *)); +static char *fixit __P((char *, char *)); +static int typedefed __P((definition *, char *)); + +/* + * Reinitialize the world + */ +void +reinitialize() +{ + memset(curline, 0, MAXLINESIZE); + where = curline; + linenum = 0; + defined = NULL; +} +/* + * string equality + */ +int +streq(a, b) + char *a; + char *b; +{ + return (strcmp(a, b) == 0); +} +/* + * find a value in a list + */ +definition * +findval(lst, val, cmp) + list *lst; + char *val; + int (*cmp) __P((definition *, char *)); + +{ + + for (; lst != NULL; lst = lst->next) { + if ((*cmp) (lst->val, val)) { + return (lst->val); + } + } + return (NULL); +} +/* + * store a value in a list + */ +void +storeval(lstp, val) + list **lstp; + definition *val; +{ + list **l; + list *lst; + + + for (l = lstp; *l != NULL; l = (list **) & (*l)->next); + lst = ALLOC(list); + lst->val = val; + lst->next = NULL; + *l = lst; +} + +static int +findit(def, type) + definition *def; + char *type; +{ + return (streq(def->def_name, type)); +} + +static char * +fixit(type, orig) + char *type; + char *orig; +{ + definition *def; + + def = (definition *) FINDVAL(defined, type, findit); + if (def == NULL || def->def_kind != DEF_TYPEDEF) { + return (orig); + } + switch (def->def.ty.rel) { + case REL_VECTOR: + return (def->def.ty.old_type); + case REL_ALIAS: + return (fixit(def->def.ty.old_type, orig)); + default: + return (orig); + } +} + +char * +fixtype(type) + char *type; +{ + return (fixit(type, type)); +} + +char * +stringfix(type) + char *type; +{ + if (streq(type, "string")) { + return ("wrapstring"); + } else { + return (type); + } +} + +void +ptype(prefix, type, follow) + char *prefix; + char *type; + int follow; +{ + if (prefix != NULL) { + if (streq(prefix, "enum")) { + f_print(fout, "enum "); + } else { + f_print(fout, "struct "); + } + } + if (streq(type, "bool")) { + f_print(fout, "bool_t "); + } else + if (streq(type, "string")) { + f_print(fout, "char *"); + } else { + f_print(fout, "%s ", follow ? fixtype(type) : type); + } +} + +static int +typedefed(def, type) + definition *def; + char *type; +{ + if (def->def_kind != DEF_TYPEDEF || def->def.ty.old_prefix != NULL) { + return (0); + } else { + return (streq(def->def_name, type)); + } +} + +int +isvectordef(type, rel) + char *type; + relation rel; +{ + definition *def; + + for (;;) { + switch (rel) { + case REL_VECTOR: + return (!streq(type, "string")); + case REL_ARRAY: + return (0); + case REL_POINTER: + return (0); + case REL_ALIAS: + def = (definition *) FINDVAL(defined, type, typedefed); + if (def == NULL) { + return (0); + } + type = def->def.ty.old_type; + rel = def->def.ty.rel; + } + } +} + +char * +locase(str) + char *str; +{ + char c; + static char buf[100]; + char *p = buf; + + while ((c = *str++) != '\0') { + *p++ = (c >= 'A' && c <= 'Z') ? (c - 'A' + 'a') : c; + } + *p = 0; + return (buf); +} + +void +pvname_svc(pname, vnum) + char *pname; + char *vnum; +{ + f_print(fout, "%s_%s_svc", locase(pname), vnum); +} + +void +pvname(pname, vnum) + char *pname; + char *vnum; +{ + f_print(fout, "%s_%s", locase(pname), vnum); +} +/* + * print a useful (?) error message, and then die + */ +void +error(msg) + char *msg; +{ + printwhere(); + f_print(stderr, "%s, line %d: ", infilename, linenum); + f_print(stderr, "%s\n", msg); + crash(); +} +/* + * Something went wrong, unlink any files that we may have created and then + * die. + */ +void +crash() +{ + int i; + + for (i = 0; i < nfiles; i++) { + (void) unlink(outfiles[i]); + } + exit(1); +} + +void +record_open(file) + char *file; +{ + if (nfiles < NFILES) { + outfiles[nfiles++] = file; + } else { + f_print(stderr, "too many files!\n"); + crash(); + } +} + +static char expectbuf[100]; + +/* + * error, token encountered was not the expected one + */ +void +expected1(exp1) + tok_kind exp1; +{ + s_print(expectbuf, "expected '%s'", + toktostr(exp1)); + error(expectbuf); +} +/* + * error, token encountered was not one of two expected ones + */ +void +expected2(exp1, exp2) + tok_kind exp1, exp2; +{ + s_print(expectbuf, "expected '%s' or '%s'", + toktostr(exp1), + toktostr(exp2)); + error(expectbuf); +} +/* + * error, token encountered was not one of 3 expected ones + */ +void +expected3(exp1, exp2, exp3) + tok_kind exp1, exp2, exp3; +{ + s_print(expectbuf, "expected '%s', '%s' or '%s'", + toktostr(exp1), + toktostr(exp2), + toktostr(exp3)); + error(expectbuf); +} + +void +tabify(f, tab) + FILE *f; + int tab; +{ + while (tab--) { + (void) fputc('\t', f); + } +} + + +static token tokstrings[] = { + {TOK_IDENT, "identifier"}, + {TOK_CONST, "const"}, + {TOK_RPAREN, ")"}, + {TOK_LPAREN, "("}, + {TOK_RBRACE, "}"}, + {TOK_LBRACE, "{"}, + {TOK_LBRACKET, "["}, + {TOK_RBRACKET, "]"}, + {TOK_STAR, "*"}, + {TOK_COMMA, ","}, + {TOK_EQUAL, "="}, + {TOK_COLON, ":"}, + {TOK_SEMICOLON, ";"}, + {TOK_UNION, "union"}, + {TOK_STRUCT, "struct"}, + {TOK_SWITCH, "switch"}, + {TOK_CASE, "case"}, + {TOK_DEFAULT, "default"}, + {TOK_ENUM, "enum"}, + {TOK_TYPEDEF, "typedef"}, + {TOK_INT, "int"}, + {TOK_SHORT, "short"}, + {TOK_LONG, "long"}, + {TOK_UNSIGNED, "unsigned"}, + {TOK_DOUBLE, "double"}, + {TOK_FLOAT, "float"}, + {TOK_CHAR, "char"}, + {TOK_STRING, "string"}, + {TOK_OPAQUE, "opaque"}, + {TOK_BOOL, "bool"}, + {TOK_VOID, "void"}, + {TOK_PROGRAM, "program"}, + {TOK_VERSION, "version"}, + {TOK_EOF, "??????"} +}; + +static char * +toktostr(kind) + tok_kind kind; +{ + token *sp; + + for (sp = tokstrings; sp->kind != TOK_EOF && sp->kind != kind; sp++); + return (sp->str); +} + +static void +printbuf() +{ + char c; + int i; + int cnt; + +#define TABSIZE 4 + + for (i = 0; (c = curline[i]) != '\0'; i++) { + if (c == '\t') { + cnt = 8 - (i % TABSIZE); + c = ' '; + } else { + cnt = 1; + } + while (cnt--) { + (void) fputc(c, stderr); + } + } +} + +static void +printwhere() +{ + int i; + char c; + int cnt; + + printbuf(); + for (i = 0; i < where - curline; i++) { + c = curline[i]; + if (c == '\t') { + cnt = 8 - (i % TABSIZE); + } else { + cnt = 1; + } + while (cnt--) { + (void) fputc('^', stderr); + } + } + (void) fputc('\n', stderr); +} + +char * +make_argname(pname, vname) + char *pname; + char *vname; +{ + char *name; + + name = (char *) malloc(strlen(pname) + strlen(vname) + strlen(ARGEXT) + 3); + if (!name) { + fprintf(stderr, "failed in malloc"); + exit(1); + } + sprintf(name, "%s_%s_%s", locase(pname), vname, ARGEXT); + return (name); +} + +bas_type *typ_list_h; +bas_type *typ_list_t; + +void +add_type(len, type) + int len; + char *type; +{ + bas_type *ptr; + + if ((ptr = (bas_type *) malloc(sizeof(bas_type))) == (bas_type *) NULL) { + fprintf(stderr, "failed in malloc"); + exit(1); + } + ptr->name = type; + ptr->length = len; + ptr->next = NULL; + if (typ_list_t == NULL) { + typ_list_t = ptr; + typ_list_h = ptr; + } else { + typ_list_t->next = ptr; + typ_list_t = ptr; + } +} + +bas_type * +find_type(type) + char *type; +{ + bas_type *ptr; + + ptr = typ_list_h; + + + while (ptr != NULL) { + if (strcmp(ptr->name, type) == 0) + return (ptr); + else + ptr = ptr->next; + } + return (NULL); +} diff --git a/developer_cmds/rpcgen/rpc_util.h b/developer_cmds/rpcgen/rpc_util.h new file mode 100644 index 0000000..33a84b3 --- /dev/null +++ b/developer_cmds/rpcgen/rpc_util.h @@ -0,0 +1,178 @@ +/* $NetBSD: rpc_util.h,v 1.4 1997/10/11 21:01:58 christos Exp $ */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user or with the express written consent of + * Sun Microsystems, Inc. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* @(#)rpc_util.h 1.5 90/08/29 (C) 1987 SMI */ + +/* + * rpc_util.h, Useful definitions for the RPC protocol compiler + */ +#include +#include + +#define alloc(size) (void *)malloc((unsigned)(size)) +#define ALLOC(object) (object *) malloc(sizeof(object)) + +#define s_print (void) sprintf +#define f_print (void) fprintf + +struct list { + definition *val; + struct list *next; +}; +typedef struct list list; + +#define PUT 1 +#define GET 2 + +/* + * Global variables + */ +#define MAXLINESIZE 1024 +extern char curline[MAXLINESIZE]; +extern char *where; +extern int linenum; + +extern char *infilename; +extern FILE *fout; +extern FILE *fin; + +extern list *defined; + + +extern bas_type *typ_list_h; +extern bas_type *typ_list_t; + +/* + * All the option flags + */ +extern int inetdflag; +extern int pmflag; +extern int tblflag; +extern int logflag; +extern int newstyle; +extern int Cflag; /* C++ flag */ +extern int tirpcflag; /* flag for generating tirpc code */ +extern int doinline; /* if this is 0, then do not generate inline code */ +extern int callerflag; + +/* + * Other flags related with inetd jumpstart. + */ +extern int indefinitewait; +extern int exitnow; +extern int timerflag; + +extern int nonfatalerrors; + +extern pid_t childpid; + +/* + * rpc_util routines + */ + +#define STOREVAL(list,item) \ + storeval(list,item) + +#define FINDVAL(list,item,finder) \ + findval(list, item, finder) + +void reinitialize __P((void)); +int streq __P((char *, char *)); +definition *findval __P((list *, char *, int (*)(definition *, char *))); +void storeval __P((list **, definition *)); +char *fixtype __P((char *)); +char *stringfix __P((char *)); +void ptype __P((char *, char *, int)); +int isvectordef __P((char *, relation)); +char *locase __P((char *)); +void pvname_svc __P((char *, char *)); +void pvname __P((char *, char *)); +void error __P((char *)); +void crash __P((void)); +void record_open __P((char *)); +void expected1 __P((tok_kind)); +void expected2 __P((tok_kind, tok_kind )); +void expected3 __P((tok_kind, tok_kind, tok_kind)); +void tabify __P((FILE *, int)); +void record_open __P((char *)); +char *make_argname __P((char *, char *)); +void add_type __P((int, char *)); +bas_type *find_type __P((char *)); +/* + * rpc_cout routines + */ +void emit __P((definition *)); +void emit_inline __P((declaration *, int)); +void emit_single_in_line __P((declaration *, int, relation)); +char *upcase __P((char *)); + +/* + * rpc_hout routines + */ + +void print_datadef __P((definition *)); +void print_funcdef __P((definition *)); +void pxdrfuncdecl __P((char *, int)); +void pprocdef __P((proc_list *, version_list *, char *, int, int)); +void pdeclaration __P((char *, declaration *, int, char *)); + +/* + * rpc_svcout routines + */ +void write_most __P((char *, int, int)); +void write_netid_register __P((char *)); +void write_nettype_register __P((char *)); +void write_rest __P((void)); +void write_programs __P((char *)); +int nullproc __P((proc_list *)); +void write_svc_aux __P((int)); +void write_msg_out __P((void)); +void write_inetd_register __P((char *)); + +/* + * rpc_clntout routines + */ +void write_stubs __P((void)); +void printarglist __P((proc_list *, char *, char *)); + + +/* + * rpc_tblout routines + */ +void write_tables __P((void)); + +/* + * rpc_sample routines + */ +void write_sample_svc __P((definition *)); +int write_sample_clnt __P((definition *)); +void add_sample_msg __P((void)); +void write_sample_clnt_main __P((void)); diff --git a/developer_cmds/rpcgen/rpcgen.1 b/developer_cmds/rpcgen/rpcgen.1 new file mode 100644 index 0000000..a5764a6 --- /dev/null +++ b/developer_cmds/rpcgen/rpcgen.1 @@ -0,0 +1,452 @@ +.\" $NetBSD: rpcgen.1,v 1.8 1998/04/28 07:19:29 fair Exp $ +.\" from: @(#)rpcgen.new.1 1.1 90/11/09 TIRPC 1.0; from 40.10 of 10/10/89 +.\" Copyright (c) 1988,1990 Sun Microsystems, Inc. - All Rights Reserved. +.Dd June 11, 1995 +.Dt RPCGEN 1 +.Sh NAME +.Nm rpcgen +.Nd Remote Procedure Call (RPC) protocol compiler +.Sh SYNOPSIS +.Nm +.Ar infile +.Nm +.Op Fl D Op Ar name=value +.Op Fl A +.Op Fl M +.Op Fl T +.Op Fl K Ar secs +.Ar infile +.Nm +.Op Fl L +.Fl c Li | +.Fl h Li | +.Fl l Li | +.Fl m Li | +.Fl t Li | +.Fl S\&c Li | +.Fl S\&s Li | +.Op Fl o Ar outfile +.Op Ar infile +.Nm +.Fl c Li | +.Ar nettype +.Op Fl o Ar outfile +.Op Ar infile +.Nm +.Fl s Li | +.Ar netid +.Op Fl o Ar outfile +.Op Ar infile +.Sh DESCRIPTION +.Nm +is a tool that generates C code to implement an +.Tn RPC +protocol. +The input to +.Nm +is a language similar to C known as +.Tn RPC +Language (Remote Procedure Call Language). +.Nm +is normally used as in the first synopsis where +it takes an input file and generates up to four output files. +If the +.Ar infile +is named +.Pa proto.x , +then +.Nm +will generate a header file in +.Pa proto.h , +.Tn XDR +routines in +.Pa proto_xdr.c , +server-side stubs in +.Pa proto_svc.c , +and client-side stubs in +.Pa proto_clnt.c . +With the +.Fl T +option, +it will also generate the +.Tn RPC +dispatch table in +.Pa proto_tbl.i . +With the +.Fl S\&c +option, +it will also generate sample code which would illustrate how to use the +remote procedures on the client side. This code would be created in +.Pa proto_client.c . +With the +.Fl S\&s +option, +it will also generate a sample server code which would illustrate how to write +the remote procedures. This code would be created in +.Pa proto_server.c . +.Pp +The server created can be started both by the port monitors +(for example, +.Em inetd +or +.Em listen ) +or by itself. +When it is started by a port monitor, +it creates servers only for the transport for which +the file descriptor 0 was passed. +The name of the transport must be specified +by setting up the environmental variable +.Ev PM_TRANSPORT . +When the server generated by +.Nm +is executed, +it creates server handles for all the transports +specified in +.Ev NETPATH +environment variable, +or if it is unset, +it creates server handles for all the visible transports from +.Pa /etc/netconfig +file. +.Pp +.Em Note: +the transports are chosen at run time and not at compile time. +When the server is self-started, +it backgrounds itself by default. +A special define symbol +.Dv RPC_SVC_FG +can be used to run the server process in foreground. +.P +The second synopsis provides special features which allow +for the creation of more sophisticated +.Tn RPC +servers. +These features include support for user provided +.Li #defines +and +.Tn RPC +dispatch tables. +The entries in the +.Tn RPC +dispatch table contain: +.Pp +.Bl -inset -offset indent -compact +.It + +pointers to the service routine corresponding to that procedure, +.It + +a pointer to the input and output arguments, +.It + +the size of these routines +.El +.Pp +A server can use the dispatch table to check authorization +and then to execute the service routine; +a client library may use it to deal with the details of storage +management and +.Tn XDR +data conversion. +.Pp +The other three synopses shown above are used when +one does not want to generate all the output files, +but only a particular one. +Some examples of their usage is described in the +EXAMPLE +section below. +When +.Nm +is executed with the +.Fl s +option, +it creates servers for that particular class of transports. +When +executed with the +.Fl n +option, +it creates a server for the transport specified by +.Em netid . +If +.Ar infile +is not specified, +.Nm +accepts the standard input. +.Pp +The C preprocessor, +.Xr cpp 1 +is run on the input file before it is actually interpreted by +.Nm +For each type of output file, +.Nm +defines a special preprocessor symbol for use by the +.Nm +programmer: +.Bl -tag -width RPC_CLNT +.It Dv RPC_HDR +defined when compiling into header files +.It Dv RPC_XDR +defined when compiling into +.Tn XDR +routines +.It Dv RPC_SVC +defined when compiling into server-side stubs +.It Dv RPC_CLNT +defined when compiling into client-side stubs +.It Dv RPC_TBL +defined when compiling into +.Tn RPC +dispatch tables +.El +.Pp +Any line beginning with +.Sq % +is passed directly into the output file, +uninterpreted by +.Nm . +.Pp +For every data type referred to in +.Ar infile +.Nm +assumes that there exists a +routine with the string +.Dq xdr_ +prepended to the name of the data type. +If this routine does not exist in the +.Tn RPC/XDR +library, it must be provided. +Providing an undefined data type +allows customization of +.Tn XDR +routines. +.Sh OPTIONS +.Bl -tag -width indent +.It Fl a +Generate all the files including sample code for client and server side. +.It Fl b +This generates code for the +.Tn "SunOS 4.1" +style of +.Tn RPC . +This is the default. +.It Fl C +Generate code in +.Tn ANSI +C. +This option also generates code that could be compiled with the +C++ compiler. +.It Fl c +Compile into +.Tn XDR +routines. +.It Fl D Ar name Ns Op Ar =value +Define a symbol +.Dv name . +Equivalent to the +.Dv #define +directive in the source. +If no +.Dv value +is given, +.Dv value +is defined as 1. +This option may be specified more than once. +.It Fl h +Compile into C data-definitions (a header file). +The +.Fl T +option can be used in conjunction to produce a +header file which supports +.Tn RPC +dispatch tables. +.It Fl K Ar secs +By default, services created using +.Nm +wait 120 seconds +after servicing a request before exiting. +That interval can be changed using the +.Fl K +flag. +To create a server that exits immediately upon servicing a request, +.Dq Fl K No 0 +can be used. +To create a server that never exits, the appropriate argument is +.Dq Fl K No -1 . +.Pp +When monitoring for a server, +some port monitors, like the +.At V.4 +utility +.Xr listen 1 , +.Em always +spawn a new process in response to a service request. +If it is known that a server will be used with such a monitor, the +server should exit immediately on completion. +For such servers, +.Nm +should be used with +.Dq Fl K No -1 . +.It Fl L +Server errors will be sent to syslog instead of stderr. +.It Fl l +Compile into client-side stubs. +.It Fl m +Compile into server-side stubs, +but do not generate a +.Fn main +routine. +This option is useful for doing callback-routines +and for users who need to write their own +.Fn main +routine to do initialization. +.It Fl N +Use the newstyle of +.Nm . +This allows procedures to have multiple arguments. +It also uses the style of parameter passing that closely resembles C. +So, when passing an argument to a remote procedure you do not have +to pass a pointer to the argument but the argument itself. +This behaviour is different from the oldstyle +of +.Nm +generated code. +The newstyle is not the default case because of backward compatibility. +.It Fl n Ar netid +Compile into server-side stubs for the transport +specified by +.Ar netid. +There should be an entry for +.Ar netid +in the +netconfig database. +This option may be specified more than once, +so as to compile a server that serves multiple transports. +.It Fl o Ar outfile +Specify the name of the output file. +If none is specified, +standard output is used +.Po +.Fl c Fl h Fl l +.Fl m Fl n Fl s +modes only +.Pc +.It Fl S\&c +Generate sample code to show the use of remote procedure and how to bind +to the server before calling the client side stubs generated by +.Nm . +.It Fl S\&s +Generate skeleton code for the remote procedures on the server side. You would need +to fill in the actual code for the remote procedures. +.It Fl s Ar nettype +Compile into server-side stubs for all the +transports belonging to the class +.Ar nettype . +The supported classes are +.Em netpath, +.Em visible, +.Em circuit_n, +.Em circuit_v, +.Em datagram_n, +.Em datagram_v, +.Em tcp, +and +.Em udp +[see +.Xr rpc 3 +for the meanings associated with these classes. +.Em Note: +.Bx +currently supports only the +.Em tcp +and +.Em udp +classes]. +This option may be specified more than once. +.Em Note: +the transports are chosen at run time and not at compile time. +.It Fl T +Generate the code to support +.Tn RPC +dispatch tables. +.It Fl t +Compile into +.Tn RPC +dispatch table. +.El +.Pp +The options +.Fl c , +.Fl h , +.Fl l , +.Fl m , +.Fl s , +and +.Fl t +are used exclusively to generate a particular type of file, +while the options +.Fl D +and +.Fl T +are global and can be used with the other options. +.Sh NOTES +The +.Tn RPC +Language does not support nesting of structures. +As a work-around, +structures can be declared at the top-level, +and their name used inside other structures in +order to achieve the same effect. +.Pp +Name clashes can occur when using program definitions, +since the apparent scoping does not really apply. +Most of these can be avoided by giving +unique names for programs, +versions, +procedures and types. +.Pp +The server code generated with +.Fl n +option refers to the transport indicated by +.Em netid +and hence is very site specific. +.Sh EXAMPLE +.Pp +The command +.Pp +.Bd -literal -offset indent +$ rpcgen -T prot.x +.Ed +.Pp +generates the five files: +.Pa prot.h , +.Pa prot_clnt.c , +.Pa prot_svc.c , +.Pa prot_xdr.c +and +.Pa prot_tbl.i . +.Pp +The following example sends the C data-definitions (header file) +to standard output. +.Pp +.Bd -literal -offset indent +$ rpcgen -h prot.x +.Ed +.Pp +To send the test version of the +.Dv -DTEST , +server side stubs for +all the transport belonging to the class +.Em datagram_n +to standard output, use: +.Pp +.Bd -literal -offset indent +$ rpcgen -s datagram_n -DTEST prot.x +.Ed +.Pp +To create the server side stubs for the transport indicated by +.Em netid +.Em tcp , +use: +.Pp +.Bd -literal -offset indent +$ rpcgen -n tcp -o prot_svc.c prot.x +.Ed +.Sh SEE ALSO +.Xr cpp 1 diff --git a/developer_cmds/unifdef/unifdef.1 b/developer_cmds/unifdef/unifdef.1 new file mode 100644 index 0000000..292ee67 --- /dev/null +++ b/developer_cmds/unifdef/unifdef.1 @@ -0,0 +1,415 @@ +.\" Copyright (c) 1985, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" Copyright (c) 2002 - 2010 Tony Finch . All rights reserved. +.\" +.\" This code is derived from software contributed to Berkeley by +.\" Dave Yost. It was rewritten to support ANSI C by Tony Finch. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD: src/usr.bin/unifdef/unifdef.1,v 1.30 2010/08/01 09:10:09 joel Exp $ +.\" +.Dd March 11, 2010 +.Dt UNIFDEF 1 +.Os +.Sh NAME +.Nm unifdef , unifdefall +.Nd remove preprocessor conditionals from code +.Sh SYNOPSIS +.Nm +.Op Fl bBcdeKknsStV +.Op Fl I Ns Ar path +.Op Fl D Ns Ar sym Ns Op = Ns Ar val +.Op Fl U Ns Ar sym +.Op Fl iD Ns Ar sym Ns Op = Ns Ar val +.Op Fl iU Ns Ar sym +.Ar ... +.Op Fl o Ar outfile +.Op Ar infile +.Nm unifdefall +.Op Fl I Ns Ar path +.Ar ... +.Ar file +.Sh DESCRIPTION +The +.Nm +utility selectively processes conditional +.Xr cpp 1 +directives. +It removes from a file +both the directives +and any additional text that they specify should be removed, +while otherwise leaving the file alone. +.Pp +The +.Nm +utility acts on +.Ic #if , #ifdef , #ifndef , #elif , #else , +and +.Ic #endif +lines. +A directive is only processed +if the symbols specified on the command line are sufficient to allow +.Nm +to get a definite value for its control expression. +If the result is false, +the directive and the following lines under its control are removed. +If the result is true, +only the directive is removed. +An +.Ic #ifdef +or +.Ic #ifndef +directive is passed through unchanged +if its controlling symbol is not specified on the command line. +Any +.Ic #if +or +.Ic #elif +control expression that has an unknown value or that +.Nm +cannot parse is passed through unchanged. +By default, +.Nm +ignores +.Ic #if +and +.Ic #elif +lines with constant expressions; +it can be told to process them by specifying the +.Fl k +flag on the command line. +.Pp +It understands a commonly-used subset +of the expression syntax for +.Ic #if +and +.Ic #elif +lines: +integer constants, +integer values of symbols defined on the command line, +the +.Fn defined +operator, +the operators +.Ic \&! , < , > , <= , >= , == , != , && , || , +and parenthesized expressions. +A kind of +.Dq "short circuit" +evaluation is used for the +.Ic && +operator: +if either operand is definitely false then the result is false, +even if the value of the other operand is unknown. +Similarly, +if either operand of +.Ic || +is definitely true then the result is true. +.Pp +In most cases, the +.Nm +utility does not distinguish between object-like macros +(without arguments) and function-like arguments (with arguments). +If a macro is not explicitly defined, or is defined with the +.Fl D +flag on the command-line, its arguments are ignored. +If a macro is explicitly undefined on the command line with the +.Fl U +flag, it may not have any arguments since this leads to a syntax error. +.Pp +The +.Nm +utility understands just enough about C +to know when one of the directives is inactive +because it is inside +a comment, +or affected by a backslash-continued line. +It spots unusually-formatted preprocessor directives +and knows when the layout is too odd for it to handle. +.Pp +A script called +.Nm unifdefall +can be used to remove all conditional +.Xr cpp 1 +directives from a file. +It uses +.Nm Fl s +and +.Nm cpp Fl dM +to get lists of all the controlling symbols +and their definitions (or lack thereof), +then invokes +.Nm +with appropriate arguments to process the file. +.Sh OPTIONS +.Pp +.Bl -tag -width indent -compact +.It Fl D Ns Ar sym Ns = Ns Ar val +Specify that a symbol is defined to a given value +which is used when evaluating +.Ic #if +and +.Ic #elif +control expressions. +.Pp +.It Fl D Ns Ar sym +Specify that a symbol is defined to the value 1. +.Pp +.It Fl U Ns Ar sym +Specify that a symbol is undefined. +If the same symbol appears in more than one argument, +the last occurrence dominates. +.Pp +.It Fl b +Replace removed lines with blank lines +instead of deleting them. +Mutually exclusive with the +.Fl B +option. +.Pp +.It Fl B +Compress blank lines around a deleted section. +Mutually exclusive with the +.Fl b +option. +.Pp +.It Fl c +If the +.Fl c +flag is specified, +then the operation of +.Nm +is complemented, +i.e., the lines that would have been removed or blanked +are retained and vice versa. +.Pp +.It Fl d +Turn on printing of debugging messages. +.Pp +.It Fl e +Because +.Nm +processes its input one line at a time, +it cannot remove preprocessor directives that span more than one line. +The most common example of this is a directive with a multi-line +comment hanging off its right hand end. +By default, +if +.Nm +has to process such a directive, +it will complain that the line is too obfuscated. +The +.Fl e +option changes the behaviour so that, +where possible, +such lines are left unprocessed instead of reporting an error. +.Pp +.It Fl K +Always treat the result of +.Ic && +and +.Ic || +operators as unknown if either operand is unknown, +instead of short-circuiting when unknown operands can't affect the result. +This option is for compatibility with older versions of +.Nm . +.Pp +.It Fl k +Process +.Ic #if +and +.Ic #elif +lines with constant expressions. +By default, sections controlled by such lines are passed through unchanged +because they typically start +.Dq Li "#if 0" +and are used as a kind of comment to sketch out future or past development. +It would be rude to strip them out, just as it would be for normal comments. +.Pp +.It Fl n +Add +.Li #line +directives to the output following any deleted lines, +so that errors produced when compiling the output file correspond to +line numbers in the input file. +.Pp +.It Fl o Ar outfile +Write output to the file +.Ar outfile +instead of the standard output. +If +.Ar outfile +is the same as the input file, +the output is written to a temporary file +which is renamed into place when +.Nm +completes successfully. +.Pp +.It Fl s +Instead of processing the input file as usual, +this option causes +.Nm +to produce a list of symbols that appear in expressions +that +.Nm +understands. +It is useful in conjunction with the +.Fl dM +option of +.Xr cpp 1 +for creating +.Nm +command lines. +.Pp +.It Fl S +Like the +.Fl s +option, but the nesting depth of each symbol is also printed. +This is useful for working out the number of possible combinations +of interdependent defined/undefined symbols. +.Pp +.It Fl t +Disables parsing for C comments +and line continuations, +which is useful +for plain text. +.Pp +.It Fl iD Ns Ar sym Ns Op = Ns Ar val +.It Fl iU Ns Ar sym +Ignore +.Ic #ifdef Ns s . +If your C code uses +.Ic #ifdef Ns s +to delimit non-C lines, +such as comments +or code which is under construction, +then you must tell +.Nm +which symbols are used for that purpose so that it will not try to parse +comments +and line continuations +inside those +.Ic #ifdef Ns s . +You can specify ignored symbols with +.Fl iD Ns Ar sym Ns Oo = Ns Ar val Oc +and +.Fl iU Ns Ar sym +similar to +.Fl D Ns Ar sym Ns Op = Ns Ar val +and +.Fl U Ns Ar sym +above. +.Pp +.It Fl I Ns Ar path +Specifies to +.Nm unifdefall +an additional place to look for +.Ic #include +files. +This option is ignored by +.Nm +for compatibility with +.Xr cpp 1 +and to simplify the implementation of +.Nm unifdefall . +.Pp +.It Fl V +Print version details. +.El +.Pp +The +.Nm +utility copies its output to +.Em stdout +and will take its input from +.Em stdin +if no +.Ar file +argument is given. +.Pp +The +.Nm +utility works nicely with the +.Fl D Ns Ar sym +option of +.Xr diff 1 . +.Sh EXIT STATUS +The +.Nm +utility exits 0 if the output is an exact copy of the input, +1 if not, and 2 if in trouble. +.Sh DIAGNOSTICS +.Bl -item +.It +Too many levels of nesting. +.It +Inappropriate +.Ic #elif , +.Ic #else +or +.Ic #endif . +.It +Obfuscated preprocessor control line. +.It +Premature +.Tn EOF +(with the line number of the most recent unterminated +.Ic #if ) . +.It +.Tn EOF +in comment. +.El +.Sh SEE ALSO +.Xr cpp 1 , +.Xr diff 1 +.Sh HISTORY +The +.Nm +command appeared in +.Bx 2.9 . +.Tn ANSI\~C +support was added in +.Fx 4.7 . +.Sh AUTHORS +The original implementation was written by +.An Dave Yost Aq Dave@Yost.com . +.An Tony Finch Aq dot@dotat.at +rewrote it to support +.Tn ANSI\~C . +.Sh BUGS +Expression evaluation is very limited. +.Pp +Preprocessor control lines split across more than one physical line +(because of comments or backslash-newline) +cannot be handled in every situation. +.Pp +Trigraphs are not recognized. +.Pp +There is no support for symbols with different definitions at +different points in the source file. +.Pp +The text-mode and ignore functionality does not correspond to modern +.Xr cpp 1 +behaviour. diff --git a/developer_cmds/unifdef/unifdef.c b/developer_cmds/unifdef/unifdef.c new file mode 100644 index 0000000..8c54e6e --- /dev/null +++ b/developer_cmds/unifdef/unifdef.c @@ -0,0 +1,1235 @@ +/* + * Copyright (c) 2002 - 2011 Tony Finch + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * unifdef - remove ifdef'ed lines + * + * This code was derived from software contributed to Berkeley by Dave Yost. + * It was rewritten to support ANSI C by Tony Finch. The original version + * of unifdef carried the 4-clause BSD copyright licence. None of its code + * remains in this version (though some of the names remain) so it now + * carries a more liberal licence. + * + * Wishlist: + * provide an option which will append the name of the + * appropriate symbol after #else's and #endif's + * provide an option which will check symbols after + * #else's and #endif's to see that they match their + * corresponding #ifdef or #ifndef + * + * These require better buffer handling, which would also make + * it possible to handle all "dodgy" directives correctly. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +const char copyright[] = + "@(#) $Version: unifdef-2.5.6.21f1388 $\n" + "@(#) $FreeBSD: src/usr.bin/unifdef/unifdef.c,v 1.31 2011/01/21 18:10:11 fanf Exp $\n" + "@(#) $Author: Tony Finch (dot@dotat.at) $\n" + "@(#) $URL: http://dotat.at/prog/unifdef $\n" +; + +/* types of input lines: */ +typedef enum { + LT_TRUEI, /* a true #if with ignore flag */ + LT_FALSEI, /* a false #if with ignore flag */ + LT_IF, /* an unknown #if */ + LT_TRUE, /* a true #if */ + LT_FALSE, /* a false #if */ + LT_ELIF, /* an unknown #elif */ + LT_ELTRUE, /* a true #elif */ + LT_ELFALSE, /* a false #elif */ + LT_ELSE, /* #else */ + LT_ENDIF, /* #endif */ + LT_DODGY, /* flag: directive is not on one line */ + LT_DODGY_LAST = LT_DODGY + LT_ENDIF, + LT_PLAIN, /* ordinary line */ + LT_EOF, /* end of file */ + LT_ERROR, /* unevaluable #if */ + LT_COUNT +} Linetype; + +static char const * const linetype_name[] = { + "TRUEI", "FALSEI", "IF", "TRUE", "FALSE", + "ELIF", "ELTRUE", "ELFALSE", "ELSE", "ENDIF", + "DODGY TRUEI", "DODGY FALSEI", + "DODGY IF", "DODGY TRUE", "DODGY FALSE", + "DODGY ELIF", "DODGY ELTRUE", "DODGY ELFALSE", + "DODGY ELSE", "DODGY ENDIF", + "PLAIN", "EOF", "ERROR" +}; + +/* state of #if processing */ +typedef enum { + IS_OUTSIDE, + IS_FALSE_PREFIX, /* false #if followed by false #elifs */ + IS_TRUE_PREFIX, /* first non-false #(el)if is true */ + IS_PASS_MIDDLE, /* first non-false #(el)if is unknown */ + IS_FALSE_MIDDLE, /* a false #elif after a pass state */ + IS_TRUE_MIDDLE, /* a true #elif after a pass state */ + IS_PASS_ELSE, /* an else after a pass state */ + IS_FALSE_ELSE, /* an else after a true state */ + IS_TRUE_ELSE, /* an else after only false states */ + IS_FALSE_TRAILER, /* #elifs after a true are false */ + IS_COUNT +} Ifstate; + +static char const * const ifstate_name[] = { + "OUTSIDE", "FALSE_PREFIX", "TRUE_PREFIX", + "PASS_MIDDLE", "FALSE_MIDDLE", "TRUE_MIDDLE", + "PASS_ELSE", "FALSE_ELSE", "TRUE_ELSE", + "FALSE_TRAILER" +}; + +/* state of comment parser */ +typedef enum { + NO_COMMENT = false, /* outside a comment */ + C_COMMENT, /* in a comment like this one */ + CXX_COMMENT, /* between // and end of line */ + STARTING_COMMENT, /* just after slash-backslash-newline */ + FINISHING_COMMENT, /* star-backslash-newline in a C comment */ + CHAR_LITERAL, /* inside '' */ + STRING_LITERAL /* inside "" */ +} Comment_state; + +static char const * const comment_name[] = { + "NO", "C", "CXX", "STARTING", "FINISHING", "CHAR", "STRING" +}; + +/* state of preprocessor line parser */ +typedef enum { + LS_START, /* only space and comments on this line */ + LS_HASH, /* only space, comments, and a hash */ + LS_DIRTY /* this line can't be a preprocessor line */ +} Line_state; + +static char const * const linestate_name[] = { + "START", "HASH", "DIRTY" +}; + +/* + * Minimum translation limits from ISO/IEC 9899:1999 5.2.4.1 + */ +#define MAXDEPTH 64 /* maximum #if nesting */ +#define MAXLINE 4096 /* maximum length of line */ +#define MAXSYMS 4096 /* maximum number of symbols */ + +/* + * Sometimes when editing a keyword the replacement text is longer, so + * we leave some space at the end of the tline buffer to accommodate this. + */ +#define EDITSLOP 10 + +/* + * For temporary filenames + */ +#define TEMPLATE "unifdef.XXXXXX" + +/* + * Globals. + */ + +static bool compblank; /* -B: compress blank lines */ +static bool lnblank; /* -b: blank deleted lines */ +static bool complement; /* -c: do the complement */ +static bool debugging; /* -d: debugging reports */ +static bool iocccok; /* -e: fewer IOCCC errors */ +static bool strictlogic; /* -K: keep ambiguous #ifs */ +static bool killconsts; /* -k: eval constant #ifs */ +static bool lnnum; /* -n: add #line directives */ +static bool symlist; /* -s: output symbol list */ +static bool symdepth; /* -S: output symbol depth */ +static bool text; /* -t: this is a text file */ + +static const char *symname[MAXSYMS]; /* symbol name */ +static const char *value[MAXSYMS]; /* -Dsym=value */ +static bool ignore[MAXSYMS]; /* -iDsym or -iUsym */ +static int nsyms; /* number of symbols */ + +static FILE *input; /* input file pointer */ +static const char *filename; /* input file name */ +static int linenum; /* current line number */ +static FILE *output; /* output file pointer */ +static const char *ofilename; /* output file name */ +static bool overwriting; /* output overwrites input */ +static char tempname[FILENAME_MAX]; /* used when overwriting */ + +static char tline[MAXLINE+EDITSLOP];/* input buffer plus space */ +static char *keyword; /* used for editing #elif's */ + +static const char *newline; /* input file format */ +static const char newline_unix[] = "\n"; +static const char newline_crlf[] = "\r\n"; + +static Comment_state incomment; /* comment parser state */ +static Line_state linestate; /* #if line parser state */ +static Ifstate ifstate[MAXDEPTH]; /* #if processor state */ +static bool ignoring[MAXDEPTH]; /* ignore comments state */ +static int stifline[MAXDEPTH]; /* start of current #if */ +static int depth; /* current #if nesting */ +static int delcount; /* count of deleted lines */ +static unsigned blankcount; /* count of blank lines */ +static unsigned blankmax; /* maximum recent blankcount */ +static bool constexpr; /* constant #if expression */ +static bool zerosyms = true; /* to format symdepth output */ +static bool firstsym; /* ditto */ + +static int exitstat; /* program exit status */ + +static void addsym(bool, bool, char *); +static void closeout(void); +static void debug(const char *, ...); +static void done(void); +static void error(const char *); +static int findsym(const char *); +static void flushline(bool); +static Linetype parseline(void); +static Linetype ifeval(const char **); +static void ignoreoff(void); +static void ignoreon(void); +static void keywordedit(const char *); +static void nest(void); +static void process(void); +static const char *skipargs(const char *); +static const char *skipcomment(const char *); +static const char *skipsym(const char *); +static void state(Ifstate); +static int strlcmp(const char *, const char *, size_t); +static void unnest(void); +static void usage(void); +static void version(void); + +#define endsym(c) (!isalnum((unsigned char)c) && c != '_') + +/* + * The main program. + */ +int +main(int argc, char *argv[]) +{ + int opt; + + while ((opt = getopt(argc, argv, "i:D:U:I:o:bBcdeKklnsStV")) != -1) + switch (opt) { + case 'i': /* treat stuff controlled by these symbols as text */ + /* + * For strict backwards-compatibility the U or D + * should be immediately after the -i but it doesn't + * matter much if we relax that requirement. + */ + opt = *optarg++; + if (opt == 'D') + addsym(true, true, optarg); + else if (opt == 'U') + addsym(true, false, optarg); + else + usage(); + break; + case 'D': /* define a symbol */ + addsym(false, true, optarg); + break; + case 'U': /* undef a symbol */ + addsym(false, false, optarg); + break; + case 'I': /* no-op for compatibility with cpp */ + break; + case 'b': /* blank deleted lines instead of omitting them */ + case 'l': /* backwards compatibility */ + lnblank = true; + break; + case 'B': /* compress blank lines around removed section */ + compblank = true; + break; + case 'c': /* treat -D as -U and vice versa */ + complement = true; + break; + case 'd': + debugging = true; + break; + case 'e': /* fewer errors from dodgy lines */ + iocccok = true; + break; + case 'K': /* keep ambiguous #ifs */ + strictlogic = true; + break; + case 'k': /* process constant #ifs */ + killconsts = true; + break; + case 'n': /* add #line directive after deleted lines */ + lnnum = true; + break; + case 'o': /* output to a file */ + ofilename = optarg; + break; + case 's': /* only output list of symbols that control #ifs */ + symlist = true; + break; + case 'S': /* list symbols with their nesting depth */ + symlist = symdepth = true; + break; + case 't': /* don't parse C comments */ + text = true; + break; + case 'V': /* print version */ + version(); + default: + usage(); + } + argc -= optind; + argv += optind; + if (compblank && lnblank) + errx(2, "-B and -b are mutually exclusive"); + if (argc > 1) { + errx(2, "can only do one file"); + } else if (argc == 1 && strcmp(*argv, "-") != 0) { + filename = *argv; + input = fopen(filename, "rb"); + if (input == NULL) + err(2, "can't open %s", filename); + } else { + filename = "[stdin]"; + input = stdin; + } + if (ofilename == NULL) { + ofilename = "[stdout]"; + output = stdout; + } else { + struct stat ist, ost; + if (stat(ofilename, &ost) == 0 && + fstat(fileno(input), &ist) == 0) + overwriting = (ist.st_dev == ost.st_dev + && ist.st_ino == ost.st_ino); + if (overwriting) { + const char *dirsep; + int ofd; + + dirsep = strrchr(ofilename, '/'); + if (dirsep != NULL) + snprintf(tempname, sizeof(tempname), + "%.*s/" TEMPLATE, + (int)(dirsep - ofilename), ofilename); + else + snprintf(tempname, sizeof(tempname), + TEMPLATE); + ofd = mkstemp(tempname); + if (ofd != -1) + output = fdopen(ofd, "wb+"); + if (output == NULL) + err(2, "can't create temporary file"); + fchmod(ofd, ist.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO)); + } else { + output = fopen(ofilename, "wb"); + if (output == NULL) + err(2, "can't open %s", ofilename); + } + } + process(); + abort(); /* bug */ +} + +static void +version(void) +{ + const char *c = copyright; + for (;;) { + while (*++c != '$') + if (*c == '\0') + exit(0); + while (*++c != '$') + putc(*c, stderr); + putc('\n', stderr); + } +} + +static void +usage(void) +{ + fprintf(stderr, "usage: unifdef [-bBcdeKknsStV] [-Ipath]" + " [-Dsym[=val]] [-Usym] [-iDsym[=val]] [-iUsym] ... [file]\n"); + exit(2); +} + +/* + * A state transition function alters the global #if processing state + * in a particular way. The table below is indexed by the current + * processing state and the type of the current line. + * + * Nesting is handled by keeping a stack of states; some transition + * functions increase or decrease the depth. They also maintain the + * ignore state on a stack. In some complicated cases they have to + * alter the preprocessor directive, as follows. + * + * When we have processed a group that starts off with a known-false + * #if/#elif sequence (which has therefore been deleted) followed by a + * #elif that we don't understand and therefore must keep, we edit the + * latter into a #if to keep the nesting correct. We use strncpy() to + * overwrite the 4 byte token "elif" with "if " without a '\0' byte. + * + * When we find a true #elif in a group, the following block will + * always be kept and the rest of the sequence after the next #elif or + * #else will be discarded. We edit the #elif into a #else and the + * following directive to #endif since this has the desired behaviour. + * + * "Dodgy" directives are split across multiple lines, the most common + * example being a multi-line comment hanging off the right of the + * directive. We can handle them correctly only if there is no change + * from printing to dropping (or vice versa) caused by that directive. + * If the directive is the first of a group we have a choice between + * failing with an error, or passing it through unchanged instead of + * evaluating it. The latter is not the default to avoid questions from + * users about unifdef unexpectedly leaving behind preprocessor directives. + */ +typedef void state_fn(void); + +/* report an error */ +static void Eelif (void) { error("Inappropriate #elif"); } +static void Eelse (void) { error("Inappropriate #else"); } +static void Eendif(void) { error("Inappropriate #endif"); } +static void Eeof (void) { error("Premature EOF"); } +static void Eioccc(void) { error("Obfuscated preprocessor control line"); } +/* plain line handling */ +static void print (void) { flushline(true); } +static void drop (void) { flushline(false); } +/* output lacks group's start line */ +static void Strue (void) { drop(); ignoreoff(); state(IS_TRUE_PREFIX); } +static void Sfalse(void) { drop(); ignoreoff(); state(IS_FALSE_PREFIX); } +static void Selse (void) { drop(); state(IS_TRUE_ELSE); } +/* print/pass this block */ +static void Pelif (void) { print(); ignoreoff(); state(IS_PASS_MIDDLE); } +static void Pelse (void) { print(); state(IS_PASS_ELSE); } +static void Pendif(void) { print(); unnest(); } +/* discard this block */ +static void Dfalse(void) { drop(); ignoreoff(); state(IS_FALSE_TRAILER); } +static void Delif (void) { drop(); ignoreoff(); state(IS_FALSE_MIDDLE); } +static void Delse (void) { drop(); state(IS_FALSE_ELSE); } +static void Dendif(void) { drop(); unnest(); } +/* first line of group */ +static void Fdrop (void) { nest(); Dfalse(); } +static void Fpass (void) { nest(); Pelif(); } +static void Ftrue (void) { nest(); Strue(); } +static void Ffalse(void) { nest(); Sfalse(); } +/* variable pedantry for obfuscated lines */ +static void Oiffy (void) { if (!iocccok) Eioccc(); Fpass(); ignoreon(); } +static void Oif (void) { if (!iocccok) Eioccc(); Fpass(); } +static void Oelif (void) { if (!iocccok) Eioccc(); Pelif(); } +/* ignore comments in this block */ +static void Idrop (void) { Fdrop(); ignoreon(); } +static void Itrue (void) { Ftrue(); ignoreon(); } +static void Ifalse(void) { Ffalse(); ignoreon(); } +/* modify this line */ +static void Mpass (void) { strncpy(keyword, "if ", 4); Pelif(); } +static void Mtrue (void) { keywordedit("else"); state(IS_TRUE_MIDDLE); } +static void Melif (void) { keywordedit("endif"); state(IS_FALSE_TRAILER); } +static void Melse (void) { keywordedit("endif"); state(IS_FALSE_ELSE); } + +static state_fn * const trans_table[IS_COUNT][LT_COUNT] = { +/* IS_OUTSIDE */ +{ Itrue, Ifalse,Fpass, Ftrue, Ffalse,Eelif, Eelif, Eelif, Eelse, Eendif, + Oiffy, Oiffy, Fpass, Oif, Oif, Eelif, Eelif, Eelif, Eelse, Eendif, + print, done, abort }, +/* IS_FALSE_PREFIX */ +{ Idrop, Idrop, Fdrop, Fdrop, Fdrop, Mpass, Strue, Sfalse,Selse, Dendif, + Idrop, Idrop, Fdrop, Fdrop, Fdrop, Mpass, Eioccc,Eioccc,Eioccc,Eioccc, + drop, Eeof, abort }, +/* IS_TRUE_PREFIX */ +{ Itrue, Ifalse,Fpass, Ftrue, Ffalse,Dfalse,Dfalse,Dfalse,Delse, Dendif, + Oiffy, Oiffy, Fpass, Oif, Oif, Eioccc,Eioccc,Eioccc,Eioccc,Eioccc, + print, Eeof, abort }, +/* IS_PASS_MIDDLE */ +{ Itrue, Ifalse,Fpass, Ftrue, Ffalse,Pelif, Mtrue, Delif, Pelse, Pendif, + Oiffy, Oiffy, Fpass, Oif, Oif, Pelif, Oelif, Oelif, Pelse, Pendif, + print, Eeof, abort }, +/* IS_FALSE_MIDDLE */ +{ Idrop, Idrop, Fdrop, Fdrop, Fdrop, Pelif, Mtrue, Delif, Pelse, Pendif, + Idrop, Idrop, Fdrop, Fdrop, Fdrop, Eioccc,Eioccc,Eioccc,Eioccc,Eioccc, + drop, Eeof, abort }, +/* IS_TRUE_MIDDLE */ +{ Itrue, Ifalse,Fpass, Ftrue, Ffalse,Melif, Melif, Melif, Melse, Pendif, + Oiffy, Oiffy, Fpass, Oif, Oif, Eioccc,Eioccc,Eioccc,Eioccc,Pendif, + print, Eeof, abort }, +/* IS_PASS_ELSE */ +{ Itrue, Ifalse,Fpass, Ftrue, Ffalse,Eelif, Eelif, Eelif, Eelse, Pendif, + Oiffy, Oiffy, Fpass, Oif, Oif, Eelif, Eelif, Eelif, Eelse, Pendif, + print, Eeof, abort }, +/* IS_FALSE_ELSE */ +{ Idrop, Idrop, Fdrop, Fdrop, Fdrop, Eelif, Eelif, Eelif, Eelse, Dendif, + Idrop, Idrop, Fdrop, Fdrop, Fdrop, Eelif, Eelif, Eelif, Eelse, Eioccc, + drop, Eeof, abort }, +/* IS_TRUE_ELSE */ +{ Itrue, Ifalse,Fpass, Ftrue, Ffalse,Eelif, Eelif, Eelif, Eelse, Dendif, + Oiffy, Oiffy, Fpass, Oif, Oif, Eelif, Eelif, Eelif, Eelse, Eioccc, + print, Eeof, abort }, +/* IS_FALSE_TRAILER */ +{ Idrop, Idrop, Fdrop, Fdrop, Fdrop, Dfalse,Dfalse,Dfalse,Delse, Dendif, + Idrop, Idrop, Fdrop, Fdrop, Fdrop, Dfalse,Dfalse,Dfalse,Delse, Eioccc, + drop, Eeof, abort } +/*TRUEI FALSEI IF TRUE FALSE ELIF ELTRUE ELFALSE ELSE ENDIF + TRUEI FALSEI IF TRUE FALSE ELIF ELTRUE ELFALSE ELSE ENDIF (DODGY) + PLAIN EOF ERROR */ +}; + +/* + * State machine utility functions + */ +static void +ignoreoff(void) +{ + if (depth == 0) + abort(); /* bug */ + ignoring[depth] = ignoring[depth-1]; +} +static void +ignoreon(void) +{ + ignoring[depth] = true; +} +static void +keywordedit(const char *replacement) +{ + snprintf(keyword, tline + sizeof(tline) - keyword, + "%s%s", replacement, newline); + print(); +} +static void +nest(void) +{ + if (depth > MAXDEPTH-1) + abort(); /* bug */ + if (depth == MAXDEPTH-1) + error("Too many levels of nesting"); + depth += 1; + stifline[depth] = linenum; +} +static void +unnest(void) +{ + if (depth == 0) + abort(); /* bug */ + depth -= 1; +} +static void +state(Ifstate is) +{ + ifstate[depth] = is; +} + +/* + * Write a line to the output or not, according to command line options. + * If writing fails, closeout() will print the error and exit. + */ +static void +flushline(bool keep) +{ + if (symlist) + return; + if (keep ^ complement) { + bool blankline = tline[strspn(tline, " \t\r\n")] == '\0'; + if (blankline && compblank && blankcount != blankmax) { + delcount += 1; + blankcount += 1; + } else { + if (lnnum && delcount > 0 && + fprintf(output, "#line %d%s", linenum, newline) < 0) + closeout(); + if (fputs(tline, output) == EOF) + closeout(); + delcount = 0; + blankmax = blankcount = blankline ? blankcount + 1 : 0; + } + } else { + if (lnblank && fputs(newline, output) == EOF) + closeout(); + exitstat = 1; + delcount += 1; + blankcount = 0; + } + if (debugging && fflush(output) == EOF) + closeout(); +} + +/* + * The driver for the state machine. + */ +static void +process(void) +{ + /* When compressing blank lines, act as if the file + is preceded by a large number of blank lines. */ + blankmax = blankcount = 1000; + for (;;) { + Linetype lineval = parseline(); + trans_table[ifstate[depth]][lineval](); + debug("process line %d %s -> %s depth %d", + linenum, linetype_name[lineval], + ifstate_name[ifstate[depth]], depth); + } +} + +/* + * Flush the output and handle errors. + */ +static void +closeout(void) +{ + if (symdepth && !zerosyms) + printf("\n"); + if (ferror(output) || fclose(output) == EOF) { + if (overwriting) { + warn("couldn't write to temporary file"); + unlink(tempname); + errx(2, "%s unchanged", ofilename); + } else { + err(2, "couldn't write to %s", ofilename); + } + } +} + +/* + * Clean up and exit. + */ +static void +done(void) +{ + if (incomment) + error("EOF in comment"); + closeout(); + if (overwriting && rename(tempname, ofilename) == -1) { + warn("couldn't rename temporary file"); + unlink(tempname); + errx(2, "%s unchanged", ofilename); + } + exit(exitstat); +} + +/* + * Parse a line and determine its type. We keep the preprocessor line + * parser state between calls in the global variable linestate, with + * help from skipcomment(). + */ +static Linetype +parseline(void) +{ + const char *cp; + int cursym; + int kwlen; + Linetype retval; + Comment_state wascomment; + + linenum++; + if (fgets(tline, MAXLINE, input) == NULL) { + if (ferror(input)) + error(strerror(errno)); + else + return (LT_EOF); + } + if (newline == NULL) { + if (strrchr(tline, '\n') == strrchr(tline, '\r') + 1) + newline = newline_crlf; + else + newline = newline_unix; + } + retval = LT_PLAIN; + wascomment = incomment; + cp = skipcomment(tline); + if (linestate == LS_START) { + if (*cp == '#') { + linestate = LS_HASH; + firstsym = true; + cp = skipcomment(cp + 1); + } else if (*cp != '\0') + linestate = LS_DIRTY; + } + if (!incomment && linestate == LS_HASH) { + keyword = tline + (cp - tline); + cp = skipsym(cp); + kwlen = cp - keyword; + /* no way can we deal with a continuation inside a keyword */ + if (strncmp(cp, "\\\r\n", 3) == 0 || + strncmp(cp, "\\\n", 2) == 0) + Eioccc(); + if (strlcmp("ifdef", keyword, kwlen) == 0 || + strlcmp("ifndef", keyword, kwlen) == 0) { + cp = skipcomment(cp); + if ((cursym = findsym(cp)) < 0) + retval = LT_IF; + else { + retval = (keyword[2] == 'n') + ? LT_FALSE : LT_TRUE; + if (value[cursym] == NULL) + retval = (retval == LT_TRUE) + ? LT_FALSE : LT_TRUE; + if (ignore[cursym]) + retval = (retval == LT_TRUE) + ? LT_TRUEI : LT_FALSEI; + } + cp = skipsym(cp); + } else if (strlcmp("if", keyword, kwlen) == 0) + retval = ifeval(&cp); + else if (strlcmp("elif", keyword, kwlen) == 0) + retval = ifeval(&cp) - LT_IF + LT_ELIF; + else if (strlcmp("else", keyword, kwlen) == 0) + retval = LT_ELSE; + else if (strlcmp("endif", keyword, kwlen) == 0) + retval = LT_ENDIF; + else { + linestate = LS_DIRTY; + retval = LT_PLAIN; + } + cp = skipcomment(cp); + if (*cp != '\0') { + linestate = LS_DIRTY; + if (retval == LT_TRUE || retval == LT_FALSE || + retval == LT_TRUEI || retval == LT_FALSEI) + retval = LT_IF; + if (retval == LT_ELTRUE || retval == LT_ELFALSE) + retval = LT_ELIF; + } + if (retval != LT_PLAIN && (wascomment || incomment)) { + retval += LT_DODGY; + if (incomment) + linestate = LS_DIRTY; + } + /* skipcomment normally changes the state, except + if the last line of the file lacks a newline, or + if there is too much whitespace in a directive */ + if (linestate == LS_HASH) { + size_t len = cp - tline; + if (fgets(tline + len, MAXLINE - len, input) == NULL) { + if (ferror(input)) + error(strerror(errno)); + /* append the missing newline at eof */ + strcpy(tline + len, newline); + cp += strlen(newline); + linestate = LS_START; + } else { + linestate = LS_DIRTY; + } + } + } + if (linestate == LS_DIRTY) { + while (*cp != '\0') + cp = skipcomment(cp + 1); + } + debug("parser line %d state %s comment %s line", linenum, + comment_name[incomment], linestate_name[linestate]); + return (retval); +} + +/* + * These are the binary operators that are supported by the expression + * evaluator. + */ +static Linetype op_strict(int *p, int v, Linetype at, Linetype bt) { + if(at == LT_IF || bt == LT_IF) return (LT_IF); + return (*p = v, v ? LT_TRUE : LT_FALSE); +} +static Linetype op_lt(int *p, Linetype at, int a, Linetype bt, int b) { + return op_strict(p, a < b, at, bt); +} +static Linetype op_gt(int *p, Linetype at, int a, Linetype bt, int b) { + return op_strict(p, a > b, at, bt); +} +static Linetype op_le(int *p, Linetype at, int a, Linetype bt, int b) { + return op_strict(p, a <= b, at, bt); +} +static Linetype op_ge(int *p, Linetype at, int a, Linetype bt, int b) { + return op_strict(p, a >= b, at, bt); +} +static Linetype op_eq(int *p, Linetype at, int a, Linetype bt, int b) { + return op_strict(p, a == b, at, bt); +} +static Linetype op_ne(int *p, Linetype at, int a, Linetype bt, int b) { + return op_strict(p, a != b, at, bt); +} +static Linetype op_or(int *p, Linetype at, int a, Linetype bt, int b) { + if (!strictlogic && (at == LT_TRUE || bt == LT_TRUE)) + return (*p = 1, LT_TRUE); + return op_strict(p, a || b, at, bt); +} +static Linetype op_and(int *p, Linetype at, int a, Linetype bt, int b) { + if (!strictlogic && (at == LT_FALSE || bt == LT_FALSE)) + return (*p = 0, LT_FALSE); + return op_strict(p, a && b, at, bt); +} + +/* + * An evaluation function takes three arguments, as follows: (1) a pointer to + * an element of the precedence table which lists the operators at the current + * level of precedence; (2) a pointer to an integer which will receive the + * value of the expression; and (3) a pointer to a char* that points to the + * expression to be evaluated and that is updated to the end of the expression + * when evaluation is complete. The function returns LT_FALSE if the value of + * the expression is zero, LT_TRUE if it is non-zero, LT_IF if the expression + * depends on an unknown symbol, or LT_ERROR if there is a parse failure. + */ +struct ops; + +typedef Linetype eval_fn(const struct ops *, int *, const char **); + +static eval_fn eval_table, eval_unary; + +/* + * The precedence table. Expressions involving binary operators are evaluated + * in a table-driven way by eval_table. When it evaluates a subexpression it + * calls the inner function with its first argument pointing to the next + * element of the table. Innermost expressions have special non-table-driven + * handling. + */ +static const struct ops { + eval_fn *inner; + struct op { + const char *str; + Linetype (*fn)(int *, Linetype, int, Linetype, int); + } op[5]; +} eval_ops[] = { + { eval_table, { { "||", op_or } } }, + { eval_table, { { "&&", op_and } } }, + { eval_table, { { "==", op_eq }, + { "!=", op_ne } } }, + { eval_unary, { { "<=", op_le }, + { ">=", op_ge }, + { "<", op_lt }, + { ">", op_gt } } } +}; + +/* + * Function for evaluating the innermost parts of expressions, + * viz. !expr (expr) number defined(symbol) symbol + * We reset the constexpr flag in the last two cases. + */ +static Linetype +eval_unary(const struct ops *ops, int *valp, const char **cpp) +{ + const char *cp; + char *ep; + int sym; + bool defparen; + Linetype lt; + + cp = skipcomment(*cpp); + if (*cp == '!') { + debug("eval%d !", ops - eval_ops); + cp++; + lt = eval_unary(ops, valp, &cp); + if (lt == LT_ERROR) + return (LT_ERROR); + if (lt != LT_IF) { + *valp = !*valp; + lt = *valp ? LT_TRUE : LT_FALSE; + } + } else if (*cp == '(') { + cp++; + debug("eval%d (", ops - eval_ops); + lt = eval_table(eval_ops, valp, &cp); + if (lt == LT_ERROR) + return (LT_ERROR); + cp = skipcomment(cp); + if (*cp++ != ')') + return (LT_ERROR); + } else if (isdigit((unsigned char)*cp)) { + debug("eval%d number", ops - eval_ops); + *valp = strtol(cp, &ep, 0); + if (ep == cp) + return (LT_ERROR); + lt = *valp ? LT_TRUE : LT_FALSE; + cp = skipsym(cp); + } else if (strncmp(cp, "defined", 7) == 0 && endsym(cp[7])) { + cp = skipcomment(cp+7); + debug("eval%d defined", ops - eval_ops); + if (*cp == '(') { + cp = skipcomment(cp+1); + defparen = true; + } else { + defparen = false; + } + sym = findsym(cp); + if (sym < 0) { + lt = LT_IF; + } else { + *valp = (value[sym] != NULL); + lt = *valp ? LT_TRUE : LT_FALSE; + } + cp = skipsym(cp); + cp = skipcomment(cp); + if (defparen && *cp++ != ')') + return (LT_ERROR); + constexpr = false; + } else if (!endsym(*cp)) { + debug("eval%d symbol", ops - eval_ops); + sym = findsym(cp); + cp = skipsym(cp); + if (sym < 0) { + lt = LT_IF; + cp = skipargs(cp); + } else if (value[sym] == NULL) { + *valp = 0; + lt = LT_FALSE; + } else { + *valp = strtol(value[sym], &ep, 0); + if (*ep != '\0' || ep == value[sym]) + return (LT_ERROR); + lt = *valp ? LT_TRUE : LT_FALSE; + cp = skipargs(cp); + } + constexpr = false; + } else { + debug("eval%d bad expr", ops - eval_ops); + return (LT_ERROR); + } + + *cpp = cp; + debug("eval%d = %d", ops - eval_ops, *valp); + return (lt); +} + +/* + * Table-driven evaluation of binary operators. + */ +static Linetype +eval_table(const struct ops *ops, int *valp, const char **cpp) +{ + const struct op *op; + const char *cp; + int val; + Linetype lt, rt; + + debug("eval%d", ops - eval_ops); + cp = *cpp; + lt = ops->inner(ops+1, valp, &cp); + if (lt == LT_ERROR) + return (LT_ERROR); + for (;;) { + cp = skipcomment(cp); + for (op = ops->op; op->str != NULL; op++) + if (strncmp(cp, op->str, strlen(op->str)) == 0) + break; + if (op->str == NULL) + break; + cp += strlen(op->str); + debug("eval%d %s", ops - eval_ops, op->str); + rt = ops->inner(ops+1, &val, &cp); + if (rt == LT_ERROR) + return (LT_ERROR); + lt = op->fn(valp, lt, *valp, rt, val); + } + + *cpp = cp; + debug("eval%d = %d", ops - eval_ops, *valp); + debug("eval%d lt = %s", ops - eval_ops, linetype_name[lt]); + return (lt); +} + +/* + * Evaluate the expression on a #if or #elif line. If we can work out + * the result we return LT_TRUE or LT_FALSE accordingly, otherwise we + * return just a generic LT_IF. + */ +static Linetype +ifeval(const char **cpp) +{ + int ret; + int val = 0; + + debug("eval %s", *cpp); + constexpr = killconsts ? false : true; + ret = eval_table(eval_ops, &val, cpp); + debug("eval = %d", val); + return (constexpr ? LT_IF : ret == LT_ERROR ? LT_IF : ret); +} + +/* + * Skip over comments, strings, and character literals and stop at the + * next character position that is not whitespace. Between calls we keep + * the comment state in the global variable incomment, and we also adjust + * the global variable linestate when we see a newline. + * XXX: doesn't cope with the buffer splitting inside a state transition. + */ +static const char * +skipcomment(const char *cp) +{ + if (text || ignoring[depth]) { + for (; isspace((unsigned char)*cp); cp++) + if (*cp == '\n') + linestate = LS_START; + return (cp); + } + while (*cp != '\0') + /* don't reset to LS_START after a line continuation */ + if (strncmp(cp, "\\\r\n", 3) == 0) + cp += 3; + else if (strncmp(cp, "\\\n", 2) == 0) + cp += 2; + else switch (incomment) { + case NO_COMMENT: + if (strncmp(cp, "/\\\r\n", 4) == 0) { + incomment = STARTING_COMMENT; + cp += 4; + } else if (strncmp(cp, "/\\\n", 3) == 0) { + incomment = STARTING_COMMENT; + cp += 3; + } else if (strncmp(cp, "/*", 2) == 0) { + incomment = C_COMMENT; + cp += 2; + } else if (strncmp(cp, "//", 2) == 0) { + incomment = CXX_COMMENT; + cp += 2; + } else if (strncmp(cp, "\'", 1) == 0) { + incomment = CHAR_LITERAL; + linestate = LS_DIRTY; + cp += 1; + } else if (strncmp(cp, "\"", 1) == 0) { + incomment = STRING_LITERAL; + linestate = LS_DIRTY; + cp += 1; + } else if (strncmp(cp, "\n", 1) == 0) { + linestate = LS_START; + cp += 1; + } else if (strchr(" \r\t", *cp) != NULL) { + cp += 1; + } else + return (cp); + continue; + case CXX_COMMENT: + if (strncmp(cp, "\n", 1) == 0) { + incomment = NO_COMMENT; + linestate = LS_START; + } + cp += 1; + continue; + case CHAR_LITERAL: + case STRING_LITERAL: + if ((incomment == CHAR_LITERAL && cp[0] == '\'') || + (incomment == STRING_LITERAL && cp[0] == '\"')) { + incomment = NO_COMMENT; + cp += 1; + } else if (cp[0] == '\\') { + if (cp[1] == '\0') + cp += 1; + else + cp += 2; + } else if (strncmp(cp, "\n", 1) == 0) { + if (incomment == CHAR_LITERAL) + error("unterminated char literal"); + else + error("unterminated string literal"); + } else + cp += 1; + continue; + case C_COMMENT: + if (strncmp(cp, "*\\\r\n", 4) == 0) { + incomment = FINISHING_COMMENT; + cp += 4; + } else if (strncmp(cp, "*\\\n", 3) == 0) { + incomment = FINISHING_COMMENT; + cp += 3; + } else if (strncmp(cp, "*/", 2) == 0) { + incomment = NO_COMMENT; + cp += 2; + } else + cp += 1; + continue; + case STARTING_COMMENT: + if (*cp == '*') { + incomment = C_COMMENT; + cp += 1; + } else if (*cp == '/') { + incomment = CXX_COMMENT; + cp += 1; + } else { + incomment = NO_COMMENT; + linestate = LS_DIRTY; + } + continue; + case FINISHING_COMMENT: + if (*cp == '/') { + incomment = NO_COMMENT; + cp += 1; + } else + incomment = C_COMMENT; + continue; + default: + abort(); /* bug */ + } + return (cp); +} + +/* + * Skip macro arguments. + */ +static const char * +skipargs(const char *cp) +{ + const char *ocp = cp; + int level = 0; + cp = skipcomment(cp); + if (*cp != '(') + return (cp); + do { + if (*cp == '(') + level++; + if (*cp == ')') + level--; + cp = skipcomment(cp+1); + } while (level != 0 && *cp != '\0'); + if (level == 0) + return (cp); + else + /* Rewind and re-detect the syntax error later. */ + return (ocp); +} + +/* + * Skip over an identifier. + */ +static const char * +skipsym(const char *cp) +{ + while (!endsym(*cp)) + ++cp; + return (cp); +} + +/* + * Look for the symbol in the symbol table. If it is found, we return + * the symbol table index, else we return -1. + */ +static int +findsym(const char *str) +{ + const char *cp; + int symind; + + cp = skipsym(str); + if (cp == str) + return (-1); + if (symlist) { + if (symdepth && firstsym) + printf("%s%3d", zerosyms ? "" : "\n", depth); + firstsym = zerosyms = false; + printf("%s%.*s%s", + symdepth ? " " : "", + (int)(cp-str), str, + symdepth ? "" : "\n"); + /* we don't care about the value of the symbol */ + return (0); + } + for (symind = 0; symind < nsyms; ++symind) { + if (strlcmp(symname[symind], str, cp-str) == 0) { + debug("findsym %s %s", symname[symind], + value[symind] ? value[symind] : ""); + return (symind); + } + } + return (-1); +} + +/* + * Add a symbol to the symbol table. + */ +static void +addsym(bool ignorethis, bool definethis, char *sym) +{ + int symind; + char *val; + + symind = findsym(sym); + if (symind < 0) { + if (nsyms >= MAXSYMS) + errx(2, "too many symbols"); + symind = nsyms++; + } + symname[symind] = sym; + ignore[symind] = ignorethis; + val = sym + (skipsym(sym) - sym); + if (definethis) { + if (*val == '=') { + value[symind] = val+1; + *val = '\0'; + } else if (*val == '\0') + value[symind] = "1"; + else + usage(); + } else { + if (*val != '\0') + usage(); + value[symind] = NULL; + } + debug("addsym %s=%s", symname[symind], + value[symind] ? value[symind] : "undef"); +} + +/* + * Compare s with n characters of t. + * The same as strncmp() except that it checks that s[n] == '\0'. + */ +static int +strlcmp(const char *s, const char *t, size_t n) +{ + while (n-- && *t != '\0') + if (*s != *t) + return ((unsigned char)*s - (unsigned char)*t); + else + ++s, ++t; + return ((unsigned char)*s); +} + +/* + * Diagnostics. + */ +static void +debug(const char *msg, ...) +{ + va_list ap; + + if (debugging) { + va_start(ap, msg); + vwarnx(msg, ap); + va_end(ap); + } +} + +static void +error(const char *msg) +{ + if (depth == 0) + warnx("%s: %d: %s", filename, linenum, msg); + else + warnx("%s: %d: %s (#if line %d depth %d)", + filename, linenum, msg, stifline[depth], depth); + closeout(); + errx(2, "output may be truncated"); +} diff --git a/developer_cmds/unifdef/unifdefall.sh b/developer_cmds/unifdef/unifdefall.sh new file mode 100644 index 0000000..6d6165a --- /dev/null +++ b/developer_cmds/unifdef/unifdefall.sh @@ -0,0 +1,79 @@ +#!/bin/sh +# +# unifdefall: remove all the #if's from a source file +# +# Copyright (c) 2002 - 2010 Tony Finch +# Copyright (c) 2009 - 2010 Jonathan Nieder +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $FreeBSD: src/usr.bin/unifdef/unifdefall.sh,v 1.7 2010/03/12 17:55:29 fanf Exp $ + +set -e + +unifdef="$(dirname "$0")/unifdef" +if [ ! -e "$unifdef" ] +then + unifdef=unifdef +fi + +case "$@" in +"-d "*) echo DEBUGGING 1>&2 + debug=-d + shift +esac + +basename=$(basename "$0") +tmp=$(mktemp -d "${TMPDIR:-/tmp}/$basename.XXXXXXXXXX") || exit 2 +trap 'rm -r "$tmp" || exit 2' EXIT + +export LC_ALL=C + +# list of all controlling macros +"$unifdef" $debug -s "$@" | sort | uniq >"$tmp/ctrl" +# list of all macro definitions +cpp -dM "$@" | sort | sed 's/^#define //' >"$tmp/hashdefs" +# list of defined macro names +sed 's/[^A-Za-z0-9_].*$//' <"$tmp/hashdefs" >"$tmp/alldef" +# list of undefined and defined controlling macros +comm -23 "$tmp/ctrl" "$tmp/alldef" >"$tmp/undef" +comm -12 "$tmp/ctrl" "$tmp/alldef" >"$tmp/def" +# create a sed script that extracts the controlling macro definitions +# and converts them to unifdef command-line arguments +sed 's|.*|s/^&\\(([^)]*)\\)\\{0,1\\} /-D&=/p|' <"$tmp/def" >"$tmp/script" +# create the final unifdef command +{ echo "$unifdef" $debug -k '\' + # convert the controlling undefined macros to -U arguments + sed 's/.*/-U& \\/' <"$tmp/undef" + # convert the controlling defined macros to quoted -D arguments + sed -nf "$tmp/script" <"$tmp/hashdefs" | + sed "s/'/'\\\\''/g;s/.*/'&' \\\\/" + echo '"$@"' +} >"$tmp/cmd" +case $debug in +-d) for i in ctrl hashdefs alldef undef def script cmd + do echo ==== $i + cat "$tmp/$i" + done 1>&2 +esac +# run the command we just created +sh "$tmp/cmd" "$@" diff --git a/developer_cmds/xcodescripts/install-lorder.sh b/developer_cmds/xcodescripts/install-lorder.sh new file mode 100644 index 0000000..8da52b7 --- /dev/null +++ b/developer_cmds/xcodescripts/install-lorder.sh @@ -0,0 +1,7 @@ +set -ex + +BINDIR="$DSTROOT"/"$DT_TOOLCHAIN_DIR"/usr/bin + +install -c -o root -g wheel -m 0755 \ + "$PROJECT_DIR"/lorder/lorder.sh \ + "$BINDIR"/lorder diff --git a/developer_cmds/xcodescripts/install-unifdefall.sh b/developer_cmds/xcodescripts/install-unifdefall.sh new file mode 100644 index 0000000..7424b3f --- /dev/null +++ b/developer_cmds/xcodescripts/install-unifdefall.sh @@ -0,0 +1,9 @@ +set -e -x + +BINDIR="$DSTROOT"/"$DT_TOOLCHAIN_DIR"/usr/bin +MANDIR="$DSTROOT"/"$DT_TOOLCHAIN_DIR"/usr/share/man/man1 + +ln -f "$MANDIR"/unifdef.1 "$MANDIR"/unifdefall.1 +install -c -o root -g wheel -m 0755 \ + "$PROJECT_DIR"/unifdef/unifdefall.sh \ + "$BINDIR"/unifdefall -- cgit v1.2.3-56-ge451