rsalz@bbn.com (Rich Salz) (05/11/88)
Submitted-by: cbosgd!pegasus!hansen (Tony Hansen) Posting-number: Volume 14, Issue 91 Archive-name: cdecl2/part02 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 2 (of 2)." # Contents: cdecl.c # Wrapped by rsalz@fig.bbn.com on Mon May 9 20:40:48 1988 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'cdecl.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'cdecl.c'\" else echo shar: Extracting \"'cdecl.c'\" \(25555 characters\) sed "s/^X//" >'cdecl.c' <<'END_OF_FILE' X/* X * cdecl - ANSI C and C++ declaration composer & decoder X * X * originally written X * Graham Ross X * once at tektronix!tekmdp!grahamr X * now at Context, Inc. X * X * modified to provide hints for unsupported types X * added argument lists for functions X * added 'explain cast' grammar X * added #ifdef for 'create program' feature X * ???? (sorry, I lost your name and login) X * X * conversion to ANSI C X * David Wolverton X * ihnp4!houxs!daw X * X * merged D. Wolverton's ANSI C version w/ ????'s version X * added function prototypes X * added C++ declarations X * made type combination checking table driven X * added checks for void variable combinations X * made 'create program' feature a runtime option X * added file parsing as well as just stdin X * added help message at beginning X * added prompts when on a TTY or in interactive mode X * added getopt() usage X * added -a, -r, -p, -c, -d, -D, -V, -i and -+ options X * delinted X * added #defines for those without getopt or void X * added 'set options' command X * added 'quit/exit' command X * added synonyms X * Tony Hansen X * attmail!tony, ihnp4!pegasus!hansen X * X * added extern, register, static X * added links to explain, cast, declare X * separately developed ANSI C support X * Merlyn LeRoy X * merlyn@rose3.rosemount.com X * X * merged versions from LeRoy X * added tmpfile() support X * allow more parts to be missing during explanations X * Tony Hansen X * attmail!tony, ihnp4!pegasus!hansen X */ X char cdeclsccsid[] = "@(#)cdecl.c 2.4 3/31/88"; X X#include <stdio.h> X#include <ctype.h> X#if __STDC__ || defined(DOS) X# include <stdlib.h> X# include <stddef.h> X# include <string.h> X# include <stdarg.h> X#else X# ifndef NOVARARGS X# include <varargs.h> X# endif /* ndef NOVARARGS */ char *malloc(); void free(), exit(), perror(); X# ifdef BSD X# include <strings.h> X extern int errno; X# define strrchr rindex X# define NOTMPFILE X# else X# include <string.h> X# include <errno.h> X# endif /* BSD */ X# ifdef NOVOID X# define void int X# endif /* NOVOID */ X#endif /* __STDC__ || DOS */ X X#define MB_SHORT 0001 X#define MB_LONG 0002 X#define MB_UNSIGNED 0004 X#define MB_INT 0010 X#define MB_CHAR 0020 X#define MB_FLOAT 0040 X#define MB_DOUBLE 0100 X#define MB_VOID 0200 X#define MB_SIGNED 0400 X X#define NullCP ((char*)NULL) X#ifdef dodebug X# define Debug(x) do { if (DebugFlag) (void) fprintf x; } while (0) X#else X# define Debug(x) /* nothing */ X#endif X X#if __STDC__ X char *ds(char *), *cat(char *, ...), *visible(int); X int getopt(int,char **,char *); X int main(int, char **); X int yywrap(void); X int dostdin(void); X void mbcheck(void), dohelp(void), usage(void); X void prompt(void), doprompt(void), noprompt(void); X void unsupp(char *, char *); X void notsupported(char *, char *, char *); X void yyerror(char *); X void doset(char *); X void dodeclare(char*, char*, char*, char*, char*); X void docast(char*, char*, char*, char*); X void dodexplain(char*, char*, char*, char*); X void docexplain(char*, char*, char*, char*); X void setprogname(char *); X int dotmpfile(int, char**), dofileargs(int, char**); X#else X char *ds(), *cat(), *visible(); X int getopt(); X void mbcheck(), dohelp(), usage(); X void prompt(), doprompt(), noprompt(); X void unsupp(), notsupported(); X void yyerror(); X void doset(), dodeclare(), docast(), dodexplain(), docexplain(); X void setprogname(); X int dotmpfile(), dofileargs(); X#endif /* __STDC__ */ X FILE *tmpfile(); X X/* variables used during parsing */ unsigned modbits = 0; int arbdims = 1; char *savedname = 0; char unknown_name[] = "unknown_name"; char prev = 0; /* the current type of the variable being examined */ X /* values type */ X /* p pointer */ X /* r reference */ X /* f function */ X /* a array (of arbitrary dimensions) */ X /* A array with dimensions */ X /* n name */ X /* v void */ X /* s struct | class */ X /* t simple type (int, long, etc.) */ X X/* options */ int RitchieFlag = 0; /* -r, assume Ritchie PDP C language */ int MkProgramFlag = 0; /* -c, output {} and ; after declarations */ int PreANSIFlag = 0; /* -p, assume pre-ANSI C language */ int CplusplusFlag = 0; /* -+, assume C++ language */ int OnATty = 0; /* stdin is coming from a terminal */ int Interactive = 0; /* -i, overrides OnATty */ int KeywordName = 0; /* $0 is a keyword (declare, explain, cast) */ char *progname = "cdecl"; /* $0 */ X X#if dodebug int DebugFlag = 0; /* -d, output debugging trace info */ X#endif X X#ifdef doyydebug /* compile in yacc trace statements */ X#define YYDEBUG 1 X#endif /* doyydebug */ X X#include "cdgram.c" X#include "cdlex.c" X X/* definitions (and abbreviations) for type combinations cross check table */ X#define ALWAYS 0 /* combo always okay */ X#define _ ALWAYS X#define NEVER 1 /* combo never allowed */ X#define X NEVER X#define RITCHIE 2 /* combo not allowed in Ritchie compiler */ X#define R RITCHIE X#define PREANSI 3 /* combo not allowed in Pre-ANSI compiler */ X#define P PREANSI X#define ANSI 4 /* combo not allowed anymore in ANSI compiler */ X#define A ANSI X X/* This is an lower left triangular array. If we needed */ X/* to save 9 bytes, the "long" row can be removed. */ char crosscheck[9][9] = { X /* L, I, S, C, V, U, S, F, D, */ X /* long */ _, _, _, _, _, _, _, _, _, X /* int */ _, _, _, _, _, _, _, _, _, X /* short */ X, _, _, _, _, _, _, _, _, X /* char */ X, X, X, _, _, _, _, _, _, X /* void */ X, X, X, X, _, _, _, _, _, X /* unsigned */ R, _, R, R, X, _, _, _, _, X /* signed */ P, P, P, P, X, X, _, _, _, X /* float */ A, X, X, X, X, X, X, _, _, X /* double */ P, X, X, X, X, X, X, X, _ X}; X X/* the names and bits checked for each row in the above array */ struct X { X char *name; X int bit; X } crosstypes[9] = X { X { "long", MB_LONG }, X { "int", MB_INT }, X { "short", MB_SHORT }, X { "char", MB_CHAR }, X { "void", MB_VOID }, X { "unsigned", MB_UNSIGNED }, X { "signed", MB_SIGNED }, X { "float", MB_FLOAT }, X { "double", MB_DOUBLE } X }; X X/* Run through the crosscheck array looking */ X/* for unsupported combinations of types. */ void mbcheck() X{ X register int i, j, restrict; X char *t1, *t2; X X /* Loop through the types */ X /* (skip the "long" row) */ X for (i = 1; i < 9; i++) X { X /* if this type is in use */ X if ((modbits & crosstypes[i].bit) != 0) X { X /* check for other types also in use */ X for (j = 0; j < i; j++) X { X /* this type is not in use */ X if (!(modbits & crosstypes[j].bit)) X continue; X /* check the type of restriction */ X restrict = crosscheck[i][j]; X if (restrict == ALWAYS) X continue; X t1 = crosstypes[i].name; X t2 = crosstypes[j].name; X if (restrict == NEVER) X { X notsupported("", t1, t2); X } X else if (restrict == RITCHIE) X { X if (RitchieFlag) X notsupported(" (Ritchie Compiler)", t1, t2); X } X else if (restrict == PREANSI) X { X if (PreANSIFlag || RitchieFlag) X notsupported(" (Pre-ANSI Compiler)", t1, t2); X } X else if (restrict == ANSI) X { X if (!RitchieFlag && !PreANSIFlag) X notsupported(" (ANSI Compiler)", t1, t2); X } X else X { X (void) fprintf (stderr, X "%s: Internal error in crosscheck[%d,%d]=%d!\n", X progname, i, j, restrict); X exit(1); /* NOTREACHED */ X } X } X } X } X} X X/* undefine these as they are no longer needed */ X#undef _ X#undef ALWAYS X#undef X X#undef NEVER X#undef R X#undef RITCHIE X#undef P X#undef PREANSI X#undef A X#undef ANSI X X/* Write out a message about something */ X/* being unsupported, possibly with a hint. */ void unsupp(s,hint) char *s,*hint; X{ X notsupported("", s, NullCP); X if (hint) X (void) fprintf(stderr, "\t(maybe you mean \"%s\")\n", hint); X} X X/* Write out a message about something */ X/* being unsupported on a particular compiler. */ void notsupported(compiler, type1, type2) char *compiler, *type1, *type2; X{ X if (type2) X (void) fprintf(stderr, X "Warning: Unsupported in%s C%s -- '%s' with '%s'\n", X compiler, CplusplusFlag ? "++" : "", type1, type2); X else X (void) fprintf(stderr, X "Warning: Unsupported in%s C%s -- '%s'\n", X compiler, CplusplusFlag ? "++" : "", type1); X} X X/* Called by the yacc grammar */ void yyerror(s) char *s; X{ X (void) printf("%s\n",s); X Debug((stdout, "yychar=%d\n", yychar)); X} X X/* Called by the yacc grammar */ int yywrap() X{ X return 1; X} X X/* X * Support for dynamic strings: X * cat() creates a string from the concatenation X * of a null terminated list of input strings. X * The input strings are free()'d by cat() X * (so they better have been malloc()'d). X * X * the different methods of <stdarg.h> and X * <vararg.h> are handled within these macros X */ X#if __STDC__ X# define VA_DCL(type,var) (type var,...) X# define VA_START(list,var,type) ((va_start(list,var)) , (var)) X#else X#if defined(DOS) X# define VA_DCL(type,var) (var,...) type var; X# define VA_START(list,var,type) ((va_start(list,var)) , (var)) X#else X#ifndef NOVARARGS X# define VA_DCL(type,var) (va_alist) va_dcl X# define VA_START(list,var,type) ((va_start(list)) , va_arg(list,type)) X#else X /* X * it is assumed here that machines which don't have either X * <varargs.h> or <stdarg.h> will put its arguments on X * the stack in the "usual" way and consequently can grab X * the arguments using the "take the address of the first X * parameter and increment by sizeof" trick. X */ X# define VA_DCL(type,var) (var) type var; X# define VA_START(list,var,type) (list = (va_list)&(var) , (var)) X# define va_arg(list,type) ((type *)(list += sizeof(type)))[-1] X# define va_end(p) /* nothing */ typedef char *va_list; X#endif /* NOVARARGS */ X#endif /* DOS */ X#endif /* __STDC__ */ X X/* VARARGS */ char *cat VA_DCL(char*, s1) X{ X register char *newstr; X register unsigned len = 1; X char *str; X va_list args; X X /* find the length which needs to be allocated */ X str = VA_START(args, s1, char*); X for ( ; str; str = va_arg(args, char*)) X len += strlen(str); X va_end(args); X X /* allocate it */ X newstr = malloc(len); X if (newstr == 0) X { X (void) fprintf (stderr, "%s: out of malloc space within cat()!\n", X progname); X exit(1); X } X newstr[0] = '\0'; X X /* copy in the strings */ X str = VA_START(args, s1, char*); X for ( ; str; str = va_arg(args, char*)) X { X (void) strcat(newstr,str); X free(str); X } X va_end(args); X X Debug((stderr, "\tcat created '%s'\n", newstr)); X return newstr; X} X X/* X * ds() makes a malloc()'d string from one that's not. X */ char *ds(s) char *s; X{ X register char *p = malloc((unsigned)(strlen(s)+1)); X X if (p) X (void) strcpy(p,s); X else X { X (void) fprintf (stderr, "%s: malloc() failed!\n", progname); X exit(1); X } X return p; X} X X/* return a visible representation of a character */ char *visible(c) int c; X{ X static char buf[5]; X X c &= 0377; X if (isprint(c)) X { X buf[0] = c; X buf[1] = '\0'; X } X else X (void) sprintf(buf,"\\%03o",c); X return buf; X} X X#ifdef NOTMPFILE X/* provide a conservative version of tmpfile() */ X/* for those systems without it. */ X/* tmpfile() returns a FILE* of a file opened */ X/* for read&write. It is supposed to be */ X/* automatically removed when it gets closed, */ X/* but here we provide a separate rmtmpfile() */ X/* function to perform that function. */ X/* Also provide several possible file names to */ X/* try for opening. */ static char *file4tmpfile = 0; X XFILE *tmpfile() X{ X static char *listtmpfiles[] = X { X "/usr/tmp/cdeclXXXXXX", X "/tmp/cdeclXXXXXX", X "/cdeclXXXXXX", X "cdeclXXXXXX", X 0 X }; X X char **listp = listtmpfiles; X for ( ; *listp; listp++) X { X FILE *retfp; X (void) mktemp(*listp); X retfp = fopen(*listp, "w+"); X if (!retfp) X continue; X file4tmpfile = *listp; X return retfp; X } X X return 0; X} X void rmtmpfile() X{ X if (file4tmpfile) X (void) unlink(file4tmpfile); X} X#else X/* provide a mock rmtmpfile() for normal systems */ X# define rmtmpfile() /* nothing */ X#endif /* NOTMPFILE */ X X#ifndef NOGETOPT extern int optind; X#else X/* This is a miniature version of getopt() which will */ X/* do just barely enough for us to get by below. */ X/* Options are not allowed to be bunched up together. */ X/* Option arguments are not supported. */ int optind = 1; X int getopt(argc,argv,optstring) char **argv; char *optstring; X{ X int ret; X char *p; X X if ((argv[optind][0] != '-') X#ifdef DOS X && (argv[optind][0] != '/') X#endif /* DOS */ X ) X return EOF; X X ret = argv[optind][1]; X optind++; X X for (p = optstring; *p; p++) X if (*p == ret) X return ret; X X (void) fprintf (stderr, "%s: illegal option -- %s\n", X progname, visible(ret)); X X return '?'; X} X#endif X X/* the help messages */ struct helpstruct X { X char *text; /* generic text */ X char *cpptext; /* C++ specific text */ X } helptext[] = X { /* up-to 23 lines of help text so it fits on (24x80) screens */ X/* 1 */{ "[] means optional; {} means 1 or more; <> means defined elsewhere", 0 }, X/* 2 */{ " commands are separated by ';' and newlines", 0 }, X/* 3 */{ "command:", 0 }, X/* 4 */{ " declare <name> as <english>", 0 }, X/* 5 */{ " cast <name> into <english>", 0 }, X/* 6 */{ " explain <gibberish>", 0 }, X/* 7 */{ " set or set options", 0 }, X/* 8 */{ " help, ?", 0 }, X/* 9 */{ " quit or exit", 0 }, X/* 10 */{ "english:", 0 }, X/* 11 */{ " function [( <decl-list> )] returning <english>", 0 }, X/* 12 */{ " array [<number>] of <english>", 0 }, X/* 13 */{ " [{ const | volatile | noalias }] pointer to <english>", X " [{const|volatile}] {pointer|reference} to [member of class <name>] <english>" }, X/* 14 */{ " <type>", 0 }, X/* 15 */{ "type:", 0 }, X/* 16 */{ " {[<storage-class>] [{<modifier>}] [<C-type>]}", 0 }, X/* 17 */{ " { struct | union | enum } <name>", X " {struct|class|union|enum} <name>" }, X/* 18 */{ "decllist: a comma separated list of <name>, <english> or <name> as <english>", 0 }, X/* 19 */{ "name: a C identifier", 0 }, X/* 20 */{ "gibberish: a C declaration, like 'int *x', or cast, like '(int *)x'", 0 }, X/* 21 */{ "storage-class: extern, static, auto, register", 0 }, X/* 22 */{ "C-type: int, char, float, double, or void", 0 }, X/* 23 */{ "modifier: short, long, signed, unsigned, const, volatile, or noalias", X "modifier: short, long, signed, unsigned, const, or volatile" }, X { 0, 0 } X }; X X/* Print out the help text */ void dohelp() X{ X register struct helpstruct *p; X register char *fmt = CplusplusFlag ? " %s\n" : "\t%s\n"; X X for (p = helptext; p->text; p++) X if (CplusplusFlag && p->cpptext) X (void) printf(fmt, p->cpptext); X else X (void) printf(fmt, p->text); X} X X/* Tell how to invoke cdecl. */ void usage() X{ X (void) fprintf (stderr, "Usage: %s [-r|-p|-a|-+] [-ci%s%s] [files...]\n", X progname, X#ifdef dodebug X "d", X#else X "", X#endif /* dodebug */ X#ifdef doyydebug X "D" X#else X "" X#endif /* doyydebug */ X ); X (void) fprintf (stderr, "\t-r Check against Ritchie PDP C Compiler\n"); X (void) fprintf (stderr, "\t-p Check against Pre-ANSI C Compiler\n"); X (void) fprintf (stderr, "\t-a Check against ANSI C Compiler%s\n", X CplusplusFlag ? "" : " (the default)"); X (void) fprintf (stderr, "\t-+ Check against C++ Compiler%s\n", X CplusplusFlag ? " (the default)" : ""); X (void) fprintf (stderr, "\t-c Create compilable output (include ; and {})\n"); X (void) fprintf (stderr, "\t-i Force interactive mode\n"); X#ifdef dodebug X (void) fprintf (stderr, "\t-d Turn on debugging mode\n"); X#endif /* dodebug */ X#ifdef doyydebug X (void) fprintf (stderr, "\t-D Turn on YACC debugging mode\n"); X#endif /* doyydebug */ X exit(1); X /* NOTREACHED */ X} X X/* Manage the prompts. */ static int prompting = 1; X void doprompt() { prompting = 1; } void noprompt() { prompting = 0; } X void prompt() X{ X if ((OnATty || Interactive) && prompting) { X (void) printf("%s> ", progname); X (void) fflush(stdout); X } X} X X/* Save away the name of the program from argv[0] */ void setprogname(argv0) char *argv0; X{ X#ifdef DOS X char *dot; X#endif /* DOS */ X X progname = strrchr(argv0, '/'); X X#ifdef DOS X if (!progname) X progname = strrchr(argv0, '\\'); X#endif /* DOS */ X X if (progname) X progname++; X else X progname = argv0; X X#ifdef DOS X dot = strchr(progname, '.'); X if (dot) X *dot = '\0'; X for (dot = progname; *dot; dot++) X *dot = tolower(*dot); X#endif /* DOS */ X} X X/* Run down the list of keywords to see if the */ X/* program is being called named as one of them */ X/* or the first argument is one of them. */ int namedkeyword(argn) char *argn; X{ X static char *cmdlist[] = X { X "explain", "declare", "cast", "help", "?", "set", 0 X }; X X /* first check the program name */ X char **cmdptr = cmdlist; X for ( ; *cmdptr; cmdptr++) X if (strcmp(*cmdptr, progname) == 0) X { X KeywordName = 1; X return 1; X } X X /* now check $1 */ X for (cmdptr = cmdlist; *cmdptr; cmdptr++) X if (strcmp(*cmdptr, argn) == 0) X return 1; X X /* nope, must be file name arguments */ X return 0; X} X X/* Read from standard input, turning */ X/* on prompting if necessary. */ int dostdin() X{ X int ret; X OnATty = isatty(0); X if (OnATty || Interactive) X { X (void) printf("Type `help' or `?' for help\n"); X prompt(); X } X X yyin = stdin; X ret = yyparse(); X OnATty = 0; X return ret; X} X X/* Write the arguments into a file */ X/* and treat that file as the input. */ int dotmpfile(argc, argv) int argc; char **argv; X{ X int ret = 0; X FILE *tmpfp = tmpfile(); X if (!tmpfp) X { X int sverrno = errno; X (void) fprintf (stderr, "%s: cannot open temp file\n", X progname); X errno = sverrno; X perror(progname); X return 1; X } X X if (KeywordName) X if (fputs(progname, tmpfp) == EOF) X { X int sverrno; X errwrite: X sverrno = errno; X (void) fprintf (stderr, "%s: error writing to temp file\n", X progname); X errno = sverrno; X perror(progname); X (void) fclose(tmpfp); X rmtmpfile(); X return 1; X } X X for ( ; optind < argc; optind++) X if (fprintf(tmpfp, " %s", argv[optind]) == EOF) X goto errwrite; X X if (putc('\n', tmpfp) == EOF) X goto errwrite; X X rewind(tmpfp); X yyin = tmpfp; X ret += yyparse(); X (void) fclose(tmpfp); X rmtmpfile(); X X return ret; X} X X/* Read each of the named files for input. */ int dofileargs(argc, argv) int argc; char **argv; X{ X FILE *ifp; X int ret = 0; X X for ( ; optind < argc; optind++) X if (strcmp(argv[optind], "-") == 0) X ret += dostdin(); X X else if ((ifp = fopen(argv[optind], "r")) == NULL) X { X int sverrno = errno; X (void) fprintf (stderr, "%s: cannot open %s\n", X progname, argv[optind]); X errno = sverrno; X perror(argv[optind]); X ret++; X } X X else X { X yyin = ifp; X ret += yyparse(); X } X X return ret; X} X X/* print out a cast */ void docast(name, left, right, type) char *name, *left, *right, *type; X{ X int lenl = strlen(left), lenr = strlen(right); X X if (prev == 'f') X unsupp("Cast into function", X "cast into pointer to function"); X else if (prev=='A' || prev=='a') X unsupp("Cast into array","cast into pointer"); X (void) printf("(%s%*s%s)%s\n", X type, lenl+lenr?lenl+1:0, X left, right, name ? name : "expression"); X free(left); X free(right); X free(type); X if (name) X free(name); X} X X/* print out a declaration */ void dodeclare(name, storage, left, right, type) char *name, *storage, *left, *right, *type; X{ X if (prev == 'v') X unsupp("Variable of type void", X "variable of type pointer to void"); X X if (*storage == 'r') X switch (prev) X { X case 'f': unsupp("Register function", NullCP); break; X case 'A': X case 'a': unsupp("Register array", NullCP); break; X case 's': unsupp("Register struct/class", NullCP); break; X } X X if (*storage) X (void) printf("%s ", storage); X (void) printf("%s %s%s%s", X type, left, X name ? name : (prev == 'f') ? "f" : "var", right); X if (MkProgramFlag) { X if ((prev == 'f') && (*storage != 'e')) X (void) printf(" { }\n"); X else X (void) printf(";\n"); X } else { X (void) printf("\n"); X } X free(storage); X free(left); X free(right); X free(type); X if (name) X free(name); X} X void dodexplain(storage, constvol, type, decl) char *storage, *constvol, *type, *decl; X{ X if (type && (strcmp(type, "void") == 0)) X if (prev == 'n') X unsupp("Variable of type void", X "variable of type pointer to void"); X else if (prev == 'a') X unsupp("array of type void", X "array of type pointer to void"); X else if (prev == 'r') X unsupp("reference to type void", X "pointer to void"); X X if (*storage == 'r') X switch (prev) X { X case 'f': unsupp("Register function", NullCP); break; X case 'A': X case 'a': unsupp("Register array", NullCP); break; X case 's': unsupp("Register struct/union/enum/class", NullCP); break; X } X X (void) printf("declare %s as ", savedname); X if (*storage) X (void) printf("%s ", storage); X (void) printf("%s", decl); X if (*constvol) X (void) printf("%s ", constvol); X (void) printf("%s\n", type ? type : "int"); X} X void docexplain(constvol, type, cast, name) char *constvol, *type, *cast, *name; X{ X if (strcmp(type, "void") == 0) X if (prev == 'a') X unsupp("array of type void", X "array of type pointer to void"); X else if (prev == 'r') X unsupp("reference to type void", X "pointer to void"); X (void) printf("cast %s into %s", name, cast); X if (strlen(constvol) > 0) X (void) printf("%s ", constvol); X (void) printf("%s\n",type); X} X X/* Do the appropriate things for the "set" command. */ void doset(opt) char *opt; X{ X if (strcmp(opt, "create") == 0) X { MkProgramFlag = 1; } X else if (strcmp(opt, "nocreate") == 0) X { MkProgramFlag = 0; } X else if (strcmp(opt, "interactive") == 0) X { Interactive = 1; } X else if (strcmp(opt, "nointeractive") == 0) X { Interactive = 0; OnATty = 0; } X else if (strcmp(opt, "ritchie") == 0) X { CplusplusFlag=0; RitchieFlag=1; PreANSIFlag=0; } X else if (strcmp(opt, "preansi") == 0) X { CplusplusFlag=0; RitchieFlag=0; PreANSIFlag=1; } X else if (strcmp(opt, "ansi") == 0) X { CplusplusFlag=0; RitchieFlag=0; PreANSIFlag=0; } X else if (strcmp(opt, "cplusplus") == 0) X { CplusplusFlag=1; RitchieFlag=0; PreANSIFlag=0; } X#ifdef dodebug X else if (strcmp(opt, "debug") == 0) X { DebugFlag = 1; } X else if (strcmp(opt, "nodebug") == 0) X { DebugFlag = 0; } X#endif /* dodebug */ X#ifdef doyydebug X else if (strcmp(opt, "yydebug") == 0) X { yydebug = 1; } X else if (strcmp(opt, "noyydebug") == 0) X { yydebug = 0; } X#endif /* doyydebug */ X else X { X if ((strcmp(opt, unknown_name) != 0) && X (strcmp(opt, "options") != 0)) X (void) printf("Unknown set option: '%s'\n", opt); X X (void) printf("Valid set options (and command line equivalents) are:\n"); X (void) printf("\toptions\n"); X (void) printf("\tcreate (-c), nocreate\n"); X (void) printf("\tinteractive (-i), nointeractive\n"); X (void) printf("\tritchie (-r), preansi (-p), ansi (-a) or cplusplus (-+)\n"); X#ifdef dodebug X (void) printf("\tdebug (-d), nodebug\n"); X#endif /* dodebug */ X#ifdef doyydebug X (void) printf("\tyydebug (-D), noyydebug\n"); X#endif /* doyydebug */ X X (void) printf("\nCurrent set values are:\n"); X (void) printf("\t%screate\n", MkProgramFlag ? " " : " no"); X (void) printf("\t%sinteractive\n", X (OnATty || Interactive) ? " " : " no"); X if (RitchieFlag) X (void) printf("\t ritchie\n"); X else X (void) printf("\t(noritchie)\n"); X if (PreANSIFlag) X (void) printf("\t preansi\n"); X else X (void) printf("\t(nopreansi)\n"); X if (!RitchieFlag && !PreANSIFlag && !CplusplusFlag) X (void) printf("\t ansi\n"); X else X (void) printf("\t(noansi)\n"); X if (CplusplusFlag) X (void) printf("\t cplusplus\n"); X else X (void) printf("\t(nocplusplus)\n"); X#ifdef dodebug X (void) printf("\t%sdebug\n", DebugFlag ? " " : " no"); X#endif /* dodebug */ X#ifdef doyydebug X (void) printf("\t%syydebug\n", yydebug ? " " : " no"); X#endif /* doyydebug */ X } X} X void versions() X{ X (void) printf("Version:\n\t%s\n\t%s\n\t%s\n", X cdeclsccsid, cdgramsccsid, cdlexsccsid); X exit(0); X} X int main(argc, argv) char **argv; X{ X int c, ret = 0; X X setprogname(argv[0]); X#ifdef DOS X if (strcmp(progname, "cppdecl") == 0) X#else X if (strcmp(progname, "c++decl") == 0) X#endif /* DOS */ X CplusplusFlag = 1; X X while ((c = getopt(argc, argv, "cirpa+dDV")) != EOF) X switch (c) X { X case 'c': MkProgramFlag=1; break; X case 'i': Interactive=1; break; X X /* The following are mutually exclusive. */ X /* Only the last one set prevails. */ X case 'r': CplusplusFlag=0; RitchieFlag=1; PreANSIFlag=0; break; X case 'p': CplusplusFlag=0; RitchieFlag=0; PreANSIFlag=1; break; X case 'a': CplusplusFlag=0; RitchieFlag=0; PreANSIFlag=0; break; X case '+': CplusplusFlag=1; RitchieFlag=0; PreANSIFlag=0; break; X X#ifdef dodebug X case 'd': DebugFlag=1; break; X#endif /* dodebug */ X#ifdef doyydebug X case 'D': yydebug=1; break; X#endif /* doyydebug */ X case 'V': versions(); break; X case '?': usage(); break; X } X X /* Run down the list of arguments, parsing each one. */ X X /* Use standard input if no file names or "-" is found. */ X if (optind == argc) X ret += dostdin(); X X /* If called as explain, declare or cast, or first */ X /* argument is one of those, use the command line */ X /* as the input. */ X else if (namedkeyword(argv[optind])) X ret += dotmpfile(argc, argv); X X else X ret += dofileargs(argc, argv); X X exit(ret); X /* NOTREACHED */ X} END_OF_FILE if test 25555 -ne `wc -c <'cdecl.c'`; then echo shar: \"'cdecl.c'\" unpacked with wrong size! fi # end of 'cdecl.c' fi echo shar: End of archive 2 \(of 2\). cp /dev/null ark2isdone MISSING="" for I in 1 2 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked both archives. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0 -- Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.