From d175a3f7fe8bfe874af43ed81f7f9c87ffa8e810 Mon Sep 17 00:00:00 2001 From: keni Date: Sun, 6 Apr 2008 00:48:40 +0000 Subject: [PATCH] makedefs conditional grep (trunk only) This code (except for some of the argument parsing changes) is not used yet. mdgrep.pl generates mdgrep.h; like the lex and yacc files we ship mdgrep.h pre-generated; there is no need for perl on end-user/end-compiler systems. (In fact mdgrep.h is so simple mdgrep.pl is probably overkill.) mdgrep.h creates an array reflecting the compiler options in effect The changes to makedefs break the Mac OS9 compile; if necessary the fix is simple and documented (but I think that port is permanently dead). With that port out of the way, makedefs can be allowed to take real options; none of the current options have been changed. Instead, a second sub-main routine has been added to handle options starting with two hyphens and all the new options start with two hyphens: --input specifies the input file (- is stdin) --output specifies the output file (- is stdout) --grep causes the input file to be filtered into the output file --grep-showvars dumps the info from the array in mdgrep.h --grep-trace turns on tracing of the grep filtering Docs for the filtering language are in the source. --- util/makedefs.c | 391 ++++++++++++++++++++++++++++++++++++++++++++++-- util/mdgrep.h | 267 +++++++++++++++++++++++++++++++++ util/mdgrep.pl | 94 ++++++++++++ 3 files changed, 743 insertions(+), 9 deletions(-) create mode 100644 util/mdgrep.h create mode 100644 util/mdgrep.pl diff --git a/util/makedefs.c b/util/makedefs.c index 313e019a7..c3acc3b14 100644 --- a/util/makedefs.c +++ b/util/makedefs.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)makedefs.c 3.5 2006/12/09 */ +/* NetHack 3.5 makedefs.c $Date$ $Revision$ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* Copyright (c) M. Stephenson, 1990, 1991. */ /* Copyright (c) Dean Luick, 1990. */ @@ -27,12 +27,12 @@ #include "patchlevel.h" #endif +#include #ifdef MAC # if defined(__SC__) || defined(__MRC__) /* MPW compilers */ # define MPWTOOL #include #include -#include # else /* MAC without MPWTOOL */ # define MACsansMPWTOOL # endif @@ -173,6 +173,7 @@ static boolean FDECL(h_filter, (char *)); static boolean FDECL(ranged_attk,(struct permonst*)); static int FDECL(mstrength,(struct permonst *)); static void NDECL(build_savebones_compat_string); +static void FDECL(do_ext_makedefs,(int , char **)); static boolean FDECL(qt_comment, (char *)); static boolean FDECL(qt_control, (char *)); @@ -222,6 +223,16 @@ main(void) else buf[len-1] = 0; /* remove return */ + if(buf[0]=='-' && buf[1]=='-'){ +#if 0 + split up buf into words + do_ext_makedefs(fakeargc, fakeargv); +#else + printf("extended makedefs not implemented for Mac OS9\n"); + exit(EXIT_FAILURE); +#endif + } + do_makedefs(buf); exit(EXIT_SUCCESS); return 0; @@ -238,6 +249,7 @@ char *argv[]; #ifdef FILE_PREFIX && (argc != 3) #endif + && !(argv[1][0]=='-' && argv[1][1]=='-') ) { Fprintf(stderr, "Bad arg count (%d).\n", argc-1); (void) fflush(stderr); @@ -250,7 +262,12 @@ char *argv[]; argc--;argv++; } #endif - do_makedefs(&argv[1][1]); + + if(argv[1][0]=='-' && argv[1][1]=='-'){ + do_ext_makedefs(argc, argv); + } else { + do_makedefs(&argv[1][1]); + } exit(EXIT_SUCCESS); /*NOTREACHED*/ return 0; @@ -258,22 +275,26 @@ char *argv[]; #endif +static void +link_sanity_check(){ + /* Note: these initializers don't do anything except guarantee that + we're linked properly. + */ + monst_init(); + objects_init(); +} + void do_makedefs(options) char *options; { boolean more_than_one; - /* Note: these initializers don't do anything except guarantee that - we're linked properly. - */ - monst_init(); - objects_init(); + link_sanity_check(); /* construct the current version number */ make_version(); - more_than_one = strlen(options) > 1; while (*options) { if (more_than_one) @@ -324,6 +345,358 @@ char *options; } +static FILE *inputfp; +static FILE *outputfp; + +#define TODO_GREP 1; +static void NDECL(do_grep); +static void NDECL(do_grep_showvars); +static int grep_trace = 0; + +static void +do_ext_makedefs(int argc, char **argv){ + int todo = 0; + + link_sanity_check(); + + argc--; argv++; /* skip program name */ + + while(argc){ + if(argv[0][0] != '-') break; + if(argv[0][1] != '-'){ + Fprintf(stderr, "Can't mix - and -- options.\n"); + exit(EXIT_FAILURE); + } +#define IS_OPTION(str) if(!strcmp(&argv[0][2], str)) +#define CONTINUE argv++, argc--; continue +#define CONSUME \ + argv++, argc--; \ + if(argc==0){Fprintf(stderr, "missing option\n"); exit(EXIT_FAILURE);} + IS_OPTION("input"){ + CONSUME; + if(!strcmp(argv[0], "-")){ + inputfp = stdin; + } else { + inputfp = fopen(argv[0], RDTMODE); + if(!inputfp){ + Fprintf(stderr, "Can't open '%s'.\n", argv[0]); + exit(EXIT_FAILURE); + } + } + CONTINUE; + } + IS_OPTION("output"){ + CONSUME; + if(!strcmp(argv[0], "-")){ + outputfp = stdout; + } else { + outputfp = fopen(argv[0], WRTMODE); + if(!outputfp){ + Fprintf(stderr, "Can't open '%s'.\n", argv[0]); + exit(EXIT_FAILURE); + } + } + CONTINUE; + } + IS_OPTION("grep"){ + if(todo){ + Fprintf(stderr, "Can't do grep and something else.\n"); + exit(EXIT_FAILURE); + } + todo = 1; + CONTINUE; + } + IS_OPTION("grep-showvars"){ + do_grep_showvars(); + exit(EXIT_SUCCESS); + } + IS_OPTION("grep-trace"){ + grep_trace = 1; + CONTINUE; + } +#ifdef notyet + IS_OPTION("grep-define"){ + } + IS_OPTION("grep-undef"){ + } + IS_OPTION("help"){ + } +#endif +#undef IS_OPTION + Fprintf(stderr, "Unknown option '%s'.\n", argv[0]); + exit(EXIT_FAILURE); + } + if(argc){ + Fprintf(stderr, "unexpected argument '%s'.\n", argv[0]); + exit(EXIT_FAILURE); + } + + switch(todo){ + default: + Fprintf(stderr, "Confused about what to do?\n"); + exit(EXIT_FAILURE); + case 0: + Fprintf(stderr, "Nothing to do?\n"); + exit(EXIT_FAILURE); + case 1: + do_grep(); break; + } +} + +/* + Filtering syntax: + Any line NOT starting with a caret is either suppressed or passed through + unchanged depending on the current conditional state. + + The default conditional state is printing on. + + Conditionals may be nested. + + makedefs will exit with a EXIT_FAILURE if any errors are detected; as many + errors as possible are detected before giving up. + + Unknown identifiers are treated as TRUE and also as an error to allow + processing to continue past the unknown identifier (note that "#undef" is + different than unknown). + + Any line starting with a caret is a control line; as in C, zero or more spaces + may be embedded in the line almost anywhere; the caret MUST be in column 1. + + Control lines: + ^^ a line starting with a (single) literal caret + ^# a comment - the line is ignored + ^?ID if defined(ID) + ^!ID if !defined(ID) + ^: else + ^. endif + +*/ +#define GREP_MAGIC '^' +#define GREP_STACK_SIZE 100 +static int grep_rewrite = 0; /* need to (possibly) rewrite lines */ +static int grep_writing = 1; /* need to copy lines to output */ +static int grep_errors = 0; +static int grep_sp = 0; +#define ST_LD(old,opp) (!!(old) | (!!(opp)<<1)) +#define ST_OLD(v) ((v) & 1) +#define ST_OPP(v) !!((v) & 2) +#define ST_ELSE 4 +static int grep_stack[GREP_STACK_SIZE] = {ST_LD(1,0)}; +static int grep_lineno = 0; + +struct grep_var { + const char *name; + int is_defined; /* 0 undef; 1 defined */ +}; +/* struct grep_var grep_vars[] in include file: */ +#include "mdgrep.h" + +static void +do_grep_showvars(){ + int x; + for(x=0;xis_defined, id); + } + return rv->is_defined; + } + + if(grep_trace){ + Fprintf(outputfp, "ID U %s\n", id); + } + Fprintf(stderr, "unknown identifier '%s' in line %d.\n", id, + grep_lineno); + grep_errors++; + return 2; /* So new features can be checked before makedefs + * is rebuilt. */ +} + +static void +grep_show_wstack(tag) + char *tag; +{ + int x; + + if(!grep_trace) return; + + Fprintf(outputfp, "%s w=%d sp=%d\t",tag,grep_writing, grep_sp); + for(x=grep_sp; x>=0 && x>grep_sp-6;x--){ + Fprintf(outputfp, "[%d]=%d ", x, grep_stack[x]); + } + Fprintf(outputfp, "\n"); +} + +static char * +do_grep_control(buf) + char *buf; +{ + int isif = 1; + char *buf0 = buf; + while(buf[0] && isspace(buf[0])) buf++; + switch(buf[0]){ + case '#': /* comment */ + break; + case '.': /* end of if level */ + if(grep_sp==0){ + Fprintf(stderr, "unmatched ^. (endif) at line %d.\n", + grep_lineno); + grep_errors++; + } else { + grep_writing = ST_OLD(grep_stack[grep_sp--]); + grep_show_wstack("pop"); + } + break; + case '!': /* if not ID */ + isif = 0; + /* FALLTHROUGH */ + case '?': /* if ID */ + if(grep_sp == GREP_STACK_SIZE-2){ + Fprintf(stderr, "stack overflow at line %d.", + grep_lineno); + exit(EXIT_FAILURE); + } + if(grep_writing){ + isif = grep_check_id(&buf[1])?isif:!isif; + grep_stack[++grep_sp] = ST_LD(grep_writing, !isif); + grep_writing = isif; + } else { + grep_stack[++grep_sp] = ST_LD(0, 0); + /* grep_writing = 0; */ + } + grep_show_wstack("push"); + break; + case ':': /* else */ + if(ST_ELSE & grep_stack[grep_sp]){ + Fprintf(stderr, +"multiple : for same conditional at line %d.\n", grep_lineno); + grep_errors++; + } + grep_writing = ST_OPP(grep_stack[grep_sp]); + grep_stack[grep_sp] |= ST_ELSE; + break; +#if defined(notyet) + case '(': /* start of expression */ +#endif + case GREP_MAGIC: /* ^^ -> ^ */ + return buf0; + default: + { + char str[10]; + if(isprint(buf[0])){ + str[0] = buf[0]; str[1] = '\0'; + } else { + sprintf(str, "0x%02x", buf[0]); + } + Fprintf(stderr, "unknown control ^%s at line %d.\n", + str, grep_lineno); + grep_errors++; + } + break; + } + return NULL; +} + +static void +do_grep_rewrite(buf) + char *buf; +{ + /* no language features use this yet */ + return; +} + +static void +do_grep(){ + char buf[16384]; /* looong, just in case */ + + if(!inputfp){ + Fprintf(stderr,"--grep requires --input\n"); + } + if(!outputfp){ + Fprintf(stderr,"--grep requires --output\n"); + } + if(!inputfp || !outputfp){ + exit(EXIT_FAILURE); + } + + while(!feof(inputfp) && !ferror(inputfp)){ + char *tmp; + char *buf1; + + if(fgets(buf, sizeof(buf), inputfp) == 0) break; + if(tmp=strchr(buf,'\n')) *tmp = '\0'; + grep_lineno++; + if(grep_trace){ + Fprintf(outputfp, "%04d %c >%s\n", + grep_lineno, + grep_writing?' ':'#', + buf + ); + } + + if(buf[0] == GREP_MAGIC){ + buf1 = do_grep_control(&buf[1]); + if(!buf1) continue; + } else { + buf1 = buf; + } + if(grep_rewrite) + do_grep_rewrite(buf1); + if(grep_writing) + Fprintf(outputfp, "%s\n", buf1); + } + if(ferror(inputfp)){ + Fprintf(stderr, "read error!\n"); + exit(EXIT_FAILURE); + } + if(ferror(outputfp)){ + Fprintf(stderr, "write error!\n"); + exit(EXIT_FAILURE); + } + fclose(inputfp); + fclose(outputfp); + if(grep_sp){ + Fprintf(stderr, "%d unterminated conditional level%s\n", + grep_sp, grep_sp==1?"":"s"); + grep_errors++; + } + if(grep_errors){ + Fprintf(stderr, "%d error%s detected.\n", grep_errors, + grep_errors==1?"":"s"); + exit(EXIT_FAILURE); + } +} + /* trivial text encryption routine which can't be broken with `tr' */ static diff --git a/util/mdgrep.h b/util/mdgrep.h new file mode 100644 index 000000000..70c08e448 --- /dev/null +++ b/util/mdgrep.h @@ -0,0 +1,267 @@ +/* + * This file generated by mdgrep.pl version 1.1. + * DO NOT EDIT! Your changes will be lost. + */ +static struct grep_var grep_vars[]={ + {"0", 0}, + {"1", 1}, +#if defined(AMIGA) + {"AMIGA", 1}, +#else + {"AMIGA", 0}, +#endif +#if defined(AMII_GRAPHICS) + {"AMII_GRAPHICS", 1}, +#else + {"AMII_GRAPHICS", 0}, +#endif +#if defined(ASCIIGRAPH) + {"ASCIIGRAPH", 1}, +#else + {"ASCIIGRAPH", 0}, +#endif +#if defined(BETA) + {"BETA", 1}, +#else + {"BETA", 0}, +#endif +#if defined(BSD_JOB_CONTROL) + {"BSD_JOB_CONTROL", 1}, +#else + {"BSD_JOB_CONTROL", 0}, +#endif +#if defined(CLIPPING) + {"CLIPPING", 1}, +#else + {"CLIPPING", 0}, +#endif +#if defined(COMPRESS) + {"COMPRESS", 1}, +#else + {"COMPRESS", 0}, +#endif +#if defined(DLB) + {"DLB", 1}, +#else + {"DLB", 0}, +#endif + {"FALSE", 0}, +#if defined(GEM_GRAPHICS) + {"GEM_GRAPHICS", 1}, +#else + {"GEM_GRAPHICS", 0}, +#endif +#if defined(GNOME_GRAPHICS) + {"GNOME_GRAPHICS", 1}, +#else + {"GNOME_GRAPHICS", 0}, +#endif +#if defined(HANGUPHANDLING) + {"HANGUPHANDLING", 1}, +#else + {"HANGUPHANDLING", 0}, +#endif +#if defined(MAC) + {"MAC", 1}, +#else + {"MAC", 0}, +#endif +#if defined(MAC_GRAPHICS) + {"MAC_GRAPHICS", 1}, +#else + {"MAC_GRAPHICS", 0}, +#endif +#if defined(MAIL) + {"MAIL", 1}, +#else + {"MAIL", 0}, +#endif +#if defined(MFLOPPY) + {"MFLOPPY", 1}, +#else + {"MFLOPPY", 0}, +#endif +#if defined(MSDOS) + {"MSDOS", 1}, +#else + {"MSDOS", 0}, +#endif +#if defined(MSWIN_GRAPHICS) + {"MSWIN_GRAPHICS", 1}, +#else + {"MSWIN_GRAPHICS", 0}, +#endif +#if defined(NOCWD_ASSUMPTIONS) + {"NOCWD_ASSUMPTIONS", 1}, +#else + {"NOCWD_ASSUMPTIONS", 0}, +#endif +#if defined(NOSAVEONHANGUP) + {"NOSAVEONHANGUP", 1}, +#else + {"NOSAVEONHANGUP", 0}, +#endif +#if defined(OS2) + {"OS2", 1}, +#else + {"OS2", 0}, +#endif +#if defined(POSIX_JOB_CONTROL) + {"POSIX_JOB_CONTROL", 1}, +#else + {"POSIX_JOB_CONTROL", 0}, +#endif +#if defined(QT_GRAPHICS) + {"QT_GRAPHICS", 1}, +#else + {"QT_GRAPHICS", 0}, +#endif +#if defined(RANDOM) + {"RANDOM", 1}, +#else + {"RANDOM", 0}, +#endif +#if defined(SAFERHANGUP) + {"SAFERHANGUP", 1}, +#else + {"SAFERHANGUP", 0}, +#endif +#if defined(SECURE) + {"SECURE", 1}, +#else + {"SECURE", 0}, +#endif +#if defined(SHELL) + {"SHELL", 1}, +#else + {"SHELL", 0}, +#endif +#if defined(SUSPEND) + {"SUSPEND", 1}, +#else + {"SUSPEND", 0}, +#endif +#if defined(TEXTCOLOR) + {"TEXTCOLOR", 1}, +#else + {"TEXTCOLOR", 0}, +#endif +#if defined(TOS) + {"TOS", 1}, +#else + {"TOS", 0}, +#endif + {"TRUE", 1}, +#if defined(TTY_GRAPHICS) + {"TTY_GRAPHICS", 1}, +#else + {"TTY_GRAPHICS", 0}, +#endif +#if defined(UNICODE_DRAWING) + {"UNICODE_DRAWING", 1}, +#else + {"UNICODE_DRAWING", 0}, +#endif +#if defined(UNICODE_PLAYERTEXT) + {"UNICODE_PLAYERTEXT", 1}, +#else + {"UNICODE_PLAYERTEXT", 0}, +#endif +#if defined(UNICODE_WIDEWINPORT) + {"UNICODE_WIDEWINPORT", 1}, +#else + {"UNICODE_WIDEWINPORT", 0}, +#endif +#if defined(UNIX) + {"UNIX", 1}, +#else + {"UNIX", 0}, +#endif +#if defined(USER_SOUNDS) + {"USER_SOUNDS", 1}, +#else + {"USER_SOUNDS", 0}, +#endif +#if defined(USE_TILES) + {"USE_TILES", 1}, +#else + {"USE_TILES", 0}, +#endif +#if defined(VAR_PLAYGROUND) + {"VAR_PLAYGROUND", 1}, +#else + {"VAR_PLAYGROUND", 0}, +#endif +#if defined(VMS) + {"VMS", 1}, +#else + {"VMS", 0}, +#endif +#if defined(WIN32) + {"WIN32", 1}, +#else + {"WIN32", 0}, +#endif +#if defined(WIN32_PLATFORM_HPCPRO) + {"WIN32_PLATFORM_HPCPRO", 1}, +#else + {"WIN32_PLATFORM_HPCPRO", 0}, +#endif +#if defined(WIN32_PLATFORM_WFSP) + {"WIN32_PLATFORM_WFSP", 1}, +#else + {"WIN32_PLATFORM_WFSP", 0}, +#endif +#if defined(WINNT) + {"WINNT", 1}, +#else + {"WINNT", 0}, +#endif +#if defined(WIN_CE) + {"WIN_CE", 1}, +#else + {"WIN_CE", 0}, +#endif +#if defined(WIN_CE_POCKETPC) + {"WIN_CE_POCKETPC", 1}, +#else + {"WIN_CE_POCKETPC", 0}, +#endif +#if defined(WIN_CE_PS2xx) + {"WIN_CE_PS2xx", 1}, +#else + {"WIN_CE_PS2xx", 0}, +#endif +#if defined(WIN_CE_SMARTPHONE) + {"WIN_CE_SMARTPHONE", 1}, +#else + {"WIN_CE_SMARTPHONE", 0}, +#endif +#if defined(WIZARD) + {"WIZARD", 1}, +#else + {"WIZARD", 0}, +#endif +#if defined(X11_GRAPHICS) + {"X11_GRAPHICS", 1}, +#else + {"X11_GRAPHICS", 0}, +#endif +#if defined(ZEROCOMP) + {"ZEROCOMP", 1}, +#else + {"ZEROCOMP", 0}, +#endif +#if defined(ZLIB_COMP) + {"ZLIB_COMP", 1}, +#else + {"ZLIB_COMP", 0}, +#endif +#if defined(__BEOS__) + {"__BEOS__", 1}, +#else + {"__BEOS__", 0}, +#endif + {0,0} +}; +/* End of file */ diff --git a/util/mdgrep.pl b/util/mdgrep.pl new file mode 100644 index 000000000..472a3611b --- /dev/null +++ b/util/mdgrep.pl @@ -0,0 +1,94 @@ +#!perl +# NetHack 3.5 makedefs.c $Date$ $Revision$ +# Copyright (c) Kenneth Lorber, Kensington, Maryland, 2008 +# NetHack may be freely redistributed. See license for details. + +# Operating Systems: +@os = qw/WIN32 MSDOS VMS UNIX TOS AMIGA MAC WINNT __BEOS__ WIN_CE OS2 + WIN_CE_SMARTPHONE WIN_CE_POCKETPC WIN_CE_PS2xx + WIN32_PLATFORM_HPCPRO WIN32_PLATFORM_WFSP/; + +# Window Systems: +@win = qw/TTY_GRAPHICS MAC_GRAPHICS AMII_GRAPHICS MSWIN_GRAPHICS X11_GRAPHICS + QT_GRAPHICS GNOME_GRAPHICS GEM_GRAPHICS/; + +# Game Features: +@feature = qw/ZEROCOMP USE_TILES ASCIIGRAPH CLIPPING TEXTCOLOR + COMPRESS ZLIB_COMP RANDOM SECURE USER_SOUNDS WIZARD + SAFERHANGUP MFLOPPY NOCWD_ASSUMPTIONS + VAR_PLAYGROUND DLB SHELL SUSPEND NOSAVEONHANGUP HANGUPHANDLING + BSD_JOB_CONTROL MAIL POSIX_JOB_CONTROL + UNICODE_DRAWING UNICODE_WIDEWINPORT UNICODE_PLAYERTEXT +/; + +# Miscellaneous +@misc = qw/BETA/; + +# JUNK: +# MICRO BSD __GNUC__ NHSTDC TERMLIB __linux__ LINUX WIN32CON NO_TERMS +# ULTRIX_PROTO TERMINFO _DCC DISPMAP OPT_DISPMAP TARGET_API_MAC_CARBON +# NOTTYGRAPHICS SYSV ULTRIX MAKEDEFS LEV_LEX_C __STDC__ +# BITCOUNT TILE_X COLORS_IN_USE CHDIR KR1ED +# apollo __APPLE__ AIX_31 PC9800 __MACH__ _GNU_SOURCE __EMX__ DGUX +# __MWERKS__ __MRC__ __BORLANDC__ LINT THINK_C __SC__ AZTEC_C __FreeBSD__ +# USE_PROTOTYPES __DJGPP__ macintosh POSIX_TYPES SUNOS4 _MSC_VER __OpenBSD__ +# GCC_WARN VOIDYYPUT FLEX_SCANNER FLEXHACK_SCANNER WIERD_LEX +# NeXT __osf__ SVR4 _AIX32 _BULL_SOURCE AUX __sgi GNUDOS +# TIMED_DELAY DEF_MAILREADER DEF_PAGER NO_SIGNAL PC_LOCKING LATTICE __GO32__ +# msleep NO_FILE_LINKS bsdi HPUX AMIFLUSH SYSFLAGS +# OVERLAY USE_TRAMPOLI USE_OVLx SPEC_LEV DGN_COMP +# SCREEN_BIOS SCREEN_DJGPPFAST SCREEN_VGA SCREEN_8514 +# EXEPATH NOTSTDC SELECTSAVED NOTPARMDECL + +# constants +@const_true = qw/1 TRUE/; +@const_false = qw/0 FALSE/; + +sub start_file { + ($rev) = ('$Revision$') =~ m/: (.*) .$/; + open(OUT, ">mdgrep.h") || die "open mkgrep.h: $!"; + print OUT <