Date: Tue, 31 Oct 1995 07:45:05 -0800 From: Paul Traina <pst@Shockwave.COM> To: FreeBSD-gnats-submit@freebsd.org Subject: bin/803: bsd m4 chokes on config script Message-ID: <199510311545.HAA17304@precipice.shockwave.com> Resent-Message-ID: <199510311550.HAA26305@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 803 >Category: bin >Synopsis: bsd m4 chokes and dies while FSF m4 works... >Confidential: no >Severity: non-critical >Priority: medium >Responsible: freebsd-bugs >State: open >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Tue Oct 31 07:50:01 PST 1995 >Last-Modified: >Originator: Paul Traina >Organization: Shockwave Engineering >Release: FreeBSD 2.1-STABLE i386 >Environment: 2.1-stable as of this week >Description: I was porting over the new gnats-3.97 beta from Cygnus. When I went to build gnats, m4 chocked and died. Input files and sample output are below. I pulled down FSF m4 and it worked just fine. As you can see from the output of m4, it's insanely confused at this point. I checked NetBSD's and Lite-2's m4 distributions to see if there were any fixes that we failed to pick up, and we are at least current with those distributions. >How-To-Repeat: /usr/bin/m4 config.m4 config.c.in output from broken m4 (edited down) -------------- char *gnats_root = NULL; char[] char[] <static char _gnats_addr GNATS_ADDR STR_MAX[] = ; char *gnats_addr GNATS_ADDR STR_MAX = _gnats_addr GNATS_ADDR STR_MAX;> = ; char[] char[] <static char _gnats_addr GNATS_ADDR STR_MAX[] = ; char *gnats_addr GNATS_ADDR STR_MAX = _gnats_addr GNATS_ADDR STR_MAX;>; )> , , char[], dnl static char _gnats_server GNATS_SERVER char[] STR_MAX[] = ; char *gnats_server GNATS_SERVER char[] STR_MAX = _gnats_server GNATS_SERVER char[] STR_MAX;dnl define(>, { ""^ _gnats_server GNATS_SERVER char[] STR_MAX }^ ) m4: missing right quote output from FSF m4 (edited down to cover same range...) --------------- char *gnats_root = NULL; static char _gnats_addr[STR_MAX] = GNATS_ADDR; char *gnats_addr = _gnats_addr; static char _gnats_server[STR_MAX] = GNATS_SERVER; config.m4: -------------- dnl dnl Macros for generating declarations in sh/C configuration dnl changequote(<,>)dnl define(<CN_CNT>, 0)dnl # of decls processed define(<CN_INIT>,)dnl initializer list contents define(<CN_KNR>,)dnl K&R initializers dnl dnl Generate the ANSI initializer list define(<CN_ANSI>,<changequote([,])translit(CN_INIT,^,[,])changequote(,)>)dnl dnl dnl Generate the decl and initializers for an integral option define(<CN_DOINT>,<<dnl int $1 = $2;dnl define(<CN_INIT>, CN_INIT { "$2"^ (char *) &$1 }^ )dnl define(<CN_KNR>, CN_KNR confs[CN_CNT].key = "$2"; dnl confs[CN_CNT].val = (char *) &$1; )>>)dnl dnl dnl Generate the decl and initializers for a string option define(<CN_DOCHARA>,<<dnl static char _$1[$3] = $2; char *$1 = _$1;dnl define(<CN_INIT>, CN_INIT { "$2"^ _$1 }^ )dnl define(<CN_KNR>, CN_KNR confs[CN_CNT].key = "$2"; confs[CN_CNT].val = $1; )>>)dnl dnl dnl Generate the decl and initializers for an option define(<CN_OPT>,<dnl changequote(<,>)dnl ifelse($3, int, CN_DOINT($1, $2), $3, char[], CN_DOCHARA($1, $2, $4))dnl define(<CN_CNT>, incr(CN_CNT))dnl changequote(,)dnl >Fix: >Audit-Trail: >Unformatted: >)dnl dnl changequote(,)dnl config.c.in -------------------- /* Configuration processing routines for GNATS -*- C -*- Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc. This file is part of GNU GNATS. GNU GNATS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU GNATS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU GNATS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* The basic idea here is to be able to use the same configuration file for sh scripts and C programs; the sh script just uses `.', but the C program has to be a bit more trickier. And a lot uglier. */ /* FIXME, maybe: Use hash table for more option-ridden programs. */ #include "config.h" #include "gnats.h" #include "pathmax.h" char *gnats_root = NULL; CN_OPT(gnats_addr, GNATS_ADDR, char[], STR_MAX) CN_OPT(gnats_server, GNATS_SERVER, char[], STR_MAX) CN_OPT(gnats_server_port, GNATS_SERVER_PORT, int) CN_OPT(gnats_service, GNATS_SERVICE, char[], STR_MAX) CN_OPT(gnats_user, GNATS_USER, char[], STR_MAX) CN_OPT(gnats_admin, GNATS_ADMIN, char[], STR_MAX) CN_OPT(def_subm, DEFAULT_SUBMITTER, char[], STR_MAX) CN_OPT(def_release, DEFAULT_RELEASE, char[], STR_MAX) CN_OPT(flag_notify, NOTIFY, int) CN_OPT(flag_ack, ACKNOWLEDGE, int) CN_OPT(keep_rec, KEEP_RECEIVED_HEADERS, int) CN_OPT(debug_mode, DEBUG_MODE, int) CN_OPT(bday_start, BDAY_START, int) CN_OPT(bday_end, BDAY_END, int) CN_OPT(bweek_start, BWEEK_START, int) CN_OPT(bweek_end, BWEEK_END, int) CN_OPT(mail_agent, MAIL_AGENT, char[], STR_MAX) CN_OPT(bindir, BINDIR, char[], STR_MAX) CN_OPT(queue_dir, QUEUE_DIR, char[], STR_MAX) struct conf { char* key; char* val; }; #ifdef __STDC__ #define STDCINIT #endif #ifdef STDCINIT static struct conf confs[] = { CN_ANSI}; #else static struct conf confs[CN_CNT]; #endif static char *fname = NULL; static char *string_extract_double_quoted (); static char *safe_strtok (); /* Read in and set the above configuration parameters */ void configure() { FILE *fp; char line[STR_MAX]; #ifndef STDCINIT CN_KNR#endif if (! gnats_root) { gnats_root = getenv ("GNATS_ROOT"); if (! gnats_root) gnats_root = X_GNATS_ROOT; } if (fname) xfree (fname); #define CONFSTR "%s/gnats-adm/config" fname = xmalloc (strlen (gnats_root) + sizeof (CONFSTR) - 1); sprintf (fname, CONFSTR, gnats_root); fp = fopen (fname, "r"); if (fp == NULL) /* no config file; no problem */ return; while (fgets (line, STR_MAX, fp) != NULL) { int i; if (*line == '#') continue; /* comment */ for (i=0; i < sizeof(confs)/sizeof(struct conf); i++) { int n = strlen(confs[i].key); if (! strncmp(confs[i].key, line, n) && line[n] == '=') { char *p = line+n+1; int d; if (sscanf (p, "%d", &d) > 0) /* NOTIFY=1 */ *((int *) confs[i].val) = d; else /* string parameter */ { /* Mimic somewhat the sh interpretation of the line. */ if (*p == '\'') strcpy (confs[i].val, safe_strtok(p+1, "'")); else if (*p == '"') strcpy (confs[i].val, string_extract_double_quoted(p+1)); else strcpy (confs[i].val, safe_strtok(p, " \t\n")); } break; } } } } static char * safe_strtok (s, d) char *s, *d; { char *r = strtok (s, d); if (!r && *s != '\n') r = strtok (s, "\n"); if (!r) r = ""; return r; } /* Lifted largely from bash/subst.c */ static char * string_extract_double_quoted (string) char *string; { register int c, j, i; /* character, temp pos, str pos */ char *temp; /* The new string we return. */ int pass_next; /* State variables for the machine. */ pass_next = 0; temp = (char *)xmalloc (strlen (string) + 1); for (j = 0, i = 0; (c = string[i]) != '\0'; i++) { /* Process a character that was quoted by a backslash. */ if (pass_next) { /* Posix.2 sez: ``The backslash shall retain its special meaning as an escape character only when followed by one of the characters: $ ` " \ <newline>''. */ if (c != '$' && c != '`' && c != '"' && c != '\\' && c != '\n') temp[j++] = '\\'; temp[j++] = c; pass_next = 0; continue; } /* A backslash protects the next character. The code just above handles preserving the backslash in front of any character but a double quote. */ if (c == '\\') { pass_next++; continue; } /* An unescaped double quote serves to terminate the string. */ if (c == '"') break; /* Add the character to the quoted string we're accumulating. */ temp[j++] = c; } temp[j] = '\0'; strcpy (string, temp); xfree (temp); return (string); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199510311545.HAA17304>