head	1.21;
access;
symbols
	netbsd-11-0-RC4:1.21
	netbsd-11-0-RC3:1.21
	netbsd-11-0-RC2:1.21
	netbsd-11-0-RC1:1.21
	perseant-exfatfs-base-20250801:1.21
	netbsd-11:1.21.0.14
	netbsd-11-base:1.21
	netbsd-10-1-RELEASE:1.21
	perseant-exfatfs-base-20240630:1.21
	perseant-exfatfs:1.21.0.12
	perseant-exfatfs-base:1.21
	netbsd-8-3-RELEASE:1.19
	netbsd-9-4-RELEASE:1.21
	netbsd-10-0-RELEASE:1.21
	netbsd-10-0-RC6:1.21
	netbsd-10-0-RC5:1.21
	netbsd-10-0-RC4:1.21
	netbsd-10-0-RC3:1.21
	netbsd-10-0-RC2:1.21
	netbsd-10-0-RC1:1.21
	netbsd-10:1.21.0.10
	netbsd-10-base:1.21
	netbsd-9-3-RELEASE:1.21
	cjep_sun2x-base1:1.21
	cjep_sun2x:1.21.0.8
	cjep_sun2x-base:1.21
	cjep_staticlib_x-base1:1.21
	netbsd-9-2-RELEASE:1.21
	cjep_staticlib_x:1.21.0.6
	cjep_staticlib_x-base:1.21
	netbsd-9-1-RELEASE:1.21
	phil-wifi-20200421:1.21
	phil-wifi-20200411:1.21
	is-mlppp:1.21.0.4
	is-mlppp-base:1.21
	phil-wifi-20200406:1.21
	netbsd-8-2-RELEASE:1.19
	netbsd-9-0-RELEASE:1.21
	netbsd-9-0-RC2:1.21
	netbsd-9-0-RC1:1.21
	phil-wifi-20191119:1.21
	netbsd-9:1.21.0.2
	netbsd-9-base:1.21
	phil-wifi-20190609:1.21
	netbsd-8-1-RELEASE:1.19
	netbsd-8-1-RC1:1.19
	pgoyette-compat-merge-20190127:1.19
	pgoyette-compat-20190127:1.19
	pgoyette-compat-20190118:1.19
	pgoyette-compat-1226:1.19
	pgoyette-compat-1126:1.19
	pgoyette-compat-1020:1.19
	pgoyette-compat-0930:1.19
	pgoyette-compat-0906:1.19
	netbsd-7-2-RELEASE:1.19
	pgoyette-compat-0728:1.19
	netbsd-8-0-RELEASE:1.19
	phil-wifi:1.19.0.46
	phil-wifi-base:1.19
	pgoyette-compat-0625:1.19
	netbsd-8-0-RC2:1.19
	pgoyette-compat-0521:1.19
	pgoyette-compat-0502:1.19
	pgoyette-compat-0422:1.19
	netbsd-8-0-RC1:1.19
	pgoyette-compat-0415:1.19
	pgoyette-compat-0407:1.19
	pgoyette-compat-0330:1.19
	pgoyette-compat-0322:1.19
	pgoyette-compat-0315:1.19
	netbsd-7-1-2-RELEASE:1.19
	pgoyette-compat:1.19.0.44
	pgoyette-compat-base:1.19
	netbsd-7-1-1-RELEASE:1.19
	matt-nb8-mediatek:1.19.0.42
	matt-nb8-mediatek-base:1.19
	perseant-stdc-iso10646:1.19.0.40
	perseant-stdc-iso10646-base:1.19
	netbsd-8:1.19.0.38
	netbsd-8-base:1.19
	prg-localcount2-base3:1.19
	prg-localcount2-base2:1.19
	prg-localcount2-base1:1.19
	prg-localcount2:1.19.0.36
	prg-localcount2-base:1.19
	pgoyette-localcount-20170426:1.19
	bouyer-socketcan-base1:1.19
	pgoyette-localcount-20170320:1.19
	netbsd-7-1:1.19.0.34
	netbsd-7-1-RELEASE:1.19
	netbsd-7-1-RC2:1.19
	netbsd-7-nhusb-base-20170116:1.19
	bouyer-socketcan:1.19.0.32
	bouyer-socketcan-base:1.19
	pgoyette-localcount-20170107:1.19
	netbsd-7-1-RC1:1.19
	pgoyette-localcount-20161104:1.19
	netbsd-7-0-2-RELEASE:1.19
	localcount-20160914:1.19
	netbsd-7-nhusb:1.19.0.30
	netbsd-7-nhusb-base:1.19
	pgoyette-localcount-20160806:1.19
	pgoyette-localcount-20160726:1.19
	pgoyette-localcount:1.19.0.28
	pgoyette-localcount-base:1.19
	netbsd-7-0-1-RELEASE:1.19
	netbsd-7-0:1.19.0.26
	netbsd-7-0-RELEASE:1.19
	netbsd-7-0-RC3:1.19
	netbsd-7-0-RC2:1.19
	netbsd-7-0-RC1:1.19
	netbsd-5-2-3-RELEASE:1.18
	netbsd-5-1-5-RELEASE:1.18
	netbsd-6-0-6-RELEASE:1.19
	netbsd-6-1-5-RELEASE:1.19
	netbsd-7:1.19.0.24
	netbsd-7-base:1.19
	yamt-pagecache-base9:1.19
	yamt-pagecache-tag8:1.19
	netbsd-6-1-4-RELEASE:1.19
	netbsd-6-0-5-RELEASE:1.19
	tls-earlyentropy:1.19.0.22
	tls-earlyentropy-base:1.19
	riastradh-xf86-video-intel-2-7-1-pre-2-21-15:1.19
	riastradh-drm2-base3:1.19
	netbsd-6-1-3-RELEASE:1.19
	netbsd-6-0-4-RELEASE:1.19
	netbsd-5-2-2-RELEASE:1.18
	netbsd-5-1-4-RELEASE:1.18
	netbsd-6-1-2-RELEASE:1.19
	netbsd-6-0-3-RELEASE:1.19
	netbsd-5-2-1-RELEASE:1.18
	netbsd-5-1-3-RELEASE:1.18
	netbsd-6-1-1-RELEASE:1.19
	riastradh-drm2-base2:1.19
	riastradh-drm2-base1:1.19
	riastradh-drm2:1.19.0.16
	riastradh-drm2-base:1.19
	netbsd-6-1:1.19.0.20
	netbsd-6-0-2-RELEASE:1.19
	netbsd-6-1-RELEASE:1.19
	netbsd-6-1-RC4:1.19
	netbsd-6-1-RC3:1.19
	agc-symver:1.19.0.18
	agc-symver-base:1.19
	netbsd-6-1-RC2:1.19
	netbsd-6-1-RC1:1.19
	yamt-pagecache-base8:1.19
	netbsd-5-2:1.18.0.40
	netbsd-6-0-1-RELEASE:1.19
	yamt-pagecache-base7:1.19
	netbsd-5-2-RELEASE:1.18
	netbsd-5-2-RC1:1.18
	matt-nb6-plus-nbase:1.19
	yamt-pagecache-base6:1.19
	netbsd-6-0:1.19.0.14
	netbsd-6-0-RELEASE:1.19
	netbsd-6-0-RC2:1.19
	tls-maxphys:1.19.0.12
	tls-maxphys-base:1.19
	matt-nb6-plus:1.19.0.10
	matt-nb6-plus-base:1.19
	netbsd-6-0-RC1:1.19
	yamt-pagecache-base5:1.19
	yamt-pagecache-base4:1.19
	netbsd-6:1.19.0.8
	netbsd-6-base:1.19
	netbsd-5-1-2-RELEASE:1.18
	netbsd-5-1-1-RELEASE:1.18
	yamt-pagecache-base3:1.19
	yamt-pagecache-base2:1.19
	yamt-pagecache:1.19.0.6
	yamt-pagecache-base:1.19
	cherry-xenmp:1.19.0.4
	cherry-xenmp-base:1.19
	bouyer-quota2-nbase:1.19
	bouyer-quota2:1.19.0.2
	bouyer-quota2-base:1.19
	matt-mips64-premerge-20101231:1.19
	matt-nb5-mips64-premerge-20101231:1.18
	matt-nb5-pq3:1.18.0.38
	matt-nb5-pq3-base:1.18
	netbsd-5-1:1.18.0.36
	netbsd-5-1-RELEASE:1.18
	netbsd-5-1-RC4:1.18
	matt-nb5-mips64-k15:1.18
	netbsd-5-1-RC3:1.18
	netbsd-5-1-RC2:1.18
	netbsd-5-1-RC1:1.18
	netbsd-5-0-2-RELEASE:1.18
	matt-nb5-mips64-premerge-20091211:1.18
	matt-premerge-20091211:1.19
	OPENBSD20091026:1.1.1.3
	OPENBSD:1.1.1
	matt-nb5-mips64-u2-k2-k4-k7-k8-k9:1.18
	matt-nb4-mips64-k7-u2a-k9b:1.18
	matt-nb5-mips64-u1-k1-k5:1.18
	matt-nb5-mips64:1.18.0.34
	netbsd-5-0-1-RELEASE:1.18
	jym-xensuspend-nbase:1.18
	netbsd-5-0:1.18.0.32
	netbsd-5-0-RELEASE:1.18
	netbsd-5-0-RC4:1.18
	netbsd-5-0-RC3:1.18
	netbsd-5-0-RC2:1.18
	jym-xensuspend:1.18.0.30
	jym-xensuspend-base:1.18
	netbsd-5-0-RC1:1.18
	netbsd-5:1.18.0.28
	netbsd-5-base:1.18
	matt-mips64-base2:1.18
	matt-mips64:1.18.0.26
	mjf-devfs2:1.18.0.24
	mjf-devfs2-base:1.18
	netbsd-4-0-1-RELEASE:1.18
	wrstuden-revivesa-base-3:1.18
	wrstuden-revivesa-base-2:1.18
	wrstuden-fixsa-newbase:1.18
	wrstuden-revivesa-base-1:1.18
	yamt-pf42-base4:1.18
	yamt-pf42-base3:1.18
	hpcarm-cleanup-nbase:1.18
	yamt-pf42-baseX:1.18
	yamt-pf42-base2:1.18
	wrstuden-revivesa:1.18.0.22
	wrstuden-revivesa-base:1.18
	yamt-pf42:1.18.0.20
	yamt-pf42-base:1.18
	keiichi-mipv6-nbase:1.18
	keiichi-mipv6:1.18.0.18
	keiichi-mipv6-base:1.18
	matt-armv6-nbase:1.18
	matt-armv6-prevmlocking:1.18
	wrstuden-fixsa-base-1:1.18
	netbsd-4-0:1.18.0.16
	netbsd-4-0-RELEASE:1.18
	cube-autoconf:1.18.0.14
	cube-autoconf-base:1.18
	netbsd-4-0-RC5:1.18
	netbsd-4-0-RC4:1.18
	netbsd-4-0-RC3:1.18
	netbsd-4-0-RC2:1.18
	netbsd-4-0-RC1:1.18
	matt-armv6:1.18.0.12
	matt-armv6-base:1.18
	matt-mips64-base:1.18
	hpcarm-cleanup:1.18.0.10
	hpcarm-cleanup-base:1.18
	netbsd-3-1-1-RELEASE:1.16
	netbsd-3-0-3-RELEASE:1.16
	wrstuden-fixsa:1.18.0.8
	wrstuden-fixsa-base:1.18
	abandoned-netbsd-4-base:1.18
	abandoned-netbsd-4:1.18.0.4
	netbsd-3-1:1.16.0.6
	netbsd-3-1-RELEASE:1.16
	netbsd-3-0-2-RELEASE:1.16
	netbsd-3-1-RC4:1.16
	netbsd-3-1-RC3:1.16
	netbsd-3-1-RC2:1.16
	netbsd-3-1-RC1:1.16
	netbsd-4:1.18.0.6
	netbsd-4-base:1.18
	chap-midi-nbase:1.18
	netbsd-3-0-1-RELEASE:1.16
	chap-midi:1.18.0.2
	chap-midi-base:1.18
	netbsd-3-0:1.16.0.4
	netbsd-3-0-RELEASE:1.16
	netbsd-3-0-RC6:1.16
	netbsd-3-0-RC5:1.16
	netbsd-3-0-RC4:1.16
	netbsd-3-0-RC3:1.16
	netbsd-3-0-RC2:1.16
	netbsd-3-0-RC1:1.16
	netbsd-2-0-3-RELEASE:1.15.2.1
	netbsd-2-1:1.15.2.1.0.4
	netbsd-2-1-RELEASE:1.15.2.1
	netbsd-2-1-RC6:1.15.2.1
	netbsd-2-1-RC5:1.15.2.1
	netbsd-2-1-RC4:1.15.2.1
	netbsd-2-1-RC3:1.15.2.1
	netbsd-2-1-RC2:1.15.2.1
	netbsd-2-1-RC1:1.15.2.1
	netbsd-2-0-2-RELEASE:1.15.2.1
	netbsd-3:1.16.0.2
	netbsd-3-base:1.16
	netbsd-2-0-1-RELEASE:1.15.2.1
	netbsd-2:1.15.2.1.0.2
	netbsd-2-base:1.15.2.1
	netbsd-2-0-RELEASE:1.15.2.1
	netbsd-2-0-RC5:1.15.2.1
	netbsd-2-0-RC4:1.15.2.1
	netbsd-2-0-RC3:1.15.2.1
	netbsd-2-0-RC2:1.15.2.1
	netbsd-2-0-RC1:1.15.2.1
	netbsd-2-0:1.15.0.2
	netbsd-2-0-base:1.15
	netbsd-1-6-PATCH002-RELEASE:1.14
	netbsd-1-6-PATCH002:1.14
	netbsd-1-6-PATCH002-RC4:1.14
	netbsd-1-6-PATCH002-RC3:1.14
	netbsd-1-6-PATCH002-RC2:1.14
	netbsd-1-6-PATCH002-RC1:1.14
	netbsd-1-6-PATCH001:1.14
	netbsd-1-6-PATCH001-RELEASE:1.14
	netbsd-1-6-PATCH001-RC3:1.14
	netbsd-1-6-PATCH001-RC2:1.14
	netbsd-1-6-PATCH001-RC1:1.14
	fvdl_fs64_base:1.14
	netbsd-1-6-RELEASE:1.14
	netbsd-1-6-RC3:1.14
	netbsd-1-6-RC2:1.14
	netbsd-1-6-RC1:1.14
	netbsd-1-6:1.14.0.2
	netbsd-1-6-base:1.14
	netbsd-1-5-PATCH003:1.9
	netbsd-1-5-PATCH002:1.9
	netbsd-1-5-PATCH001:1.9
	netbsd-1-5-RELEASE:1.9
	netbsd-1-5-BETA2:1.9
	netbsd-1-5-BETA:1.9
	netbsd-1-4-PATCH003:1.8.4.1
	netbsd-1-5-ALPHA2:1.9
	netbsd-1-5:1.9.0.8
	netbsd-1-5-base:1.9
	minoura-xpg4dl-base:1.9
	minoura-xpg4dl:1.9.0.6
	netbsd-1-4-PATCH002:1.8.4.1
	wrstuden-devbsize-19991221:1.9
	wrstuden-devbsize:1.9.0.4
	wrstuden-devbsize-base:1.9
	comdex-fall-1999:1.9.0.2
	comdex-fall-1999-base:1.9
	netbsd-1-4-PATCH001:1.8.4.1
	netbsd-1-4-RELEASE:1.8.4.1
	netbsd-1-4:1.8.0.4
	netbsd-1-4-base:1.8
	netbsd-1-3-PATCH003:1.8
	netbsd-1-3-PATCH003-CANDIDATE2:1.8
	netbsd-1-3-PATCH003-CANDIDATE1:1.8
	netbsd-1-3-PATCH003-CANDIDATE0:1.8
	netbsd-1-3-PATCH002:1.8
	netbsd-1-3-PATCH001:1.8
	netbsd-1-3-RELEASE:1.8
	netbsd-1-3-BETA:1.8
	netbsd-1-3:1.8.0.2
	netbsd-1-3-base:1.8
	netbsd-1-2-PATCH001:1.7
	netbsd-1-2-RELEASE:1.7
	netbsd-1-2-BETA:1.7
	netbsd-1-2:1.7.0.6
	netbsd-1-2-base:1.7
	netbsd-1-1-PATCH001:1.7
	netbsd-1-1-RELEASE:1.7
	netbsd-1-1:1.7.0.2
	netbsd-1-1-base:1.7
	lite-2:1.1.1.2
	CSRG:1.1.1
	netbsd-1-0-PATCH06:1.5
	netbsd-1-0-PATCH05:1.5
	netbsd-1-0-PATCH04:1.5
	netbsd-1-0-PATCH03:1.5
	netbsd-1-0-PATCH02:1.5
	netbsd-1-0-PATCH1:1.5
	netbsd-1-0-PATCH0:1.5
	netbsd-1-0-RELEASE:1.5
	netbsd-1-0:1.5.0.2
	netbsd-1-0-base:1.5
	netbsd-0-9-RELEASE:1.2
	netbsd-0-9-BETA:1.2
	netbsd-0-9-ALPHA2:1.2
	netbsd-0-9-ALPHA:1.2
	netbsd-0-9:1.2.0.2
	netbsd-0-9-base:1.2
	netbsd-0-8:1.1.1.1
	netbsd-alpha-1:1.1.1.1
	patchkit-0-2-2:1.1.1.1
	WFJ-386bsd-01:1.1.1.1
	WFJ-920714:1.1.1;
locks; strict;
comment	@ * @;


1.21
date	2019.03.26.23.31.45;	author kre;	state Exp;
branches;
next	1.20;
commitid	mSnDyXwNkYZAPVgB;

1.20
date	2019.03.26.16.39.50;	author christos;	state Exp;
branches;
next	1.19;
commitid	4DLo07Yguv2ByTgB;

1.19
date	2009.10.26.21.11.28;	author christos;	state Exp;
branches
	1.19.46.1;
next	1.18;

1.18
date	2006.05.11.01.22.20;	author mrg;	state Exp;
branches;
next	1.17;

1.17
date	2005.10.06.17.28.33;	author drochner;	state Exp;
branches;
next	1.16;

1.16
date	2004.06.20.22.20.15;	author jmc;	state Exp;
branches;
next	1.15;

1.15
date	2003.08.07.11.14.31;	author agc;	state Exp;
branches
	1.15.2.1;
next	1.14;

1.14
date	2002.01.31.19.36.47;	author tv;	state Exp;
branches;
next	1.13;

1.13
date	2002.01.21.21.49.57;	author tv;	state Exp;
branches;
next	1.12;

1.12
date	2001.11.14.06.16.08;	author tv;	state Exp;
branches;
next	1.11;

1.11
date	2001.03.05.20.26.17;	author wiz;	state Exp;
branches;
next	1.10;

1.10
date	2000.10.17.18.51.32;	author jdolecek;	state Exp;
branches;
next	1.9;

1.9
date	99.04.14.09.38.37;	author matthias;	state Exp;
branches;
next	1.8;

1.8
date	97.10.19.04.39.53;	author lukem;	state Exp;
branches
	1.8.4.1;
next	1.7;

1.7
date	95.09.28.05.37.31;	author tls;	state Exp;
branches;
next	1.6;

1.6
date	95.04.14.23.10.25;	author mycroft;	state Exp;
branches;
next	1.5;

1.5
date	94.06.19.03.58.31;	author glass;	state Exp;
branches;
next	1.4;

1.4
date	93.10.30.00.28.42;	author glass;	state Exp;
branches;
next	1.3;

1.3
date	93.08.02.17.54.38;	author mycroft;	state Exp;
branches;
next	1.2;

1.2
date	93.06.18.21.50.27;	author glass;	state Exp;
branches;
next	1.1;

1.1
date	93.03.21.09.45.37;	author cgd;	state Exp;
branches
	1.1.1.1;
next	;

1.19.46.1
date	2019.06.10.22.10.21;	author christos;	state Exp;
branches;
next	;
commitid	jtc8rnCzWiEEHGqB;

1.15.2.1
date	2004.06.22.07.20.18;	author tron;	state Exp;
branches;
next	;

1.8.4.1
date	99.04.14.09.43.54;	author matthias;	state Exp;
branches;
next	;

1.1.1.1
date	93.03.21.09.45.37;	author cgd;	state Exp;
branches;
next	1.1.1.2;

1.1.1.2
date	95.09.28.04.33.50;	author tls;	state Exp;
branches;
next	1.1.1.3;

1.1.1.3
date	2009.10.26.21.08.58;	author christos;	state Exp;
branches;
next	;


desc
@@


1.21
log
@
Use correct printf format for (struct input_file *)->lineno
SHould unbreak 32 bit host builds.
@
text
@/*	$NetBSD: expr.c,v 1.20 2019/03/26 16:39:50 christos Exp $	*/
/* $OpenBSD: expr.c,v 1.17 2006/01/20 23:10:19 espie Exp $ */
/*
 * Copyright (c) 2004 Marc Espie <espie@@cvs.openbsd.org>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */
#if HAVE_NBTOOL_CONFIG_H
#include "nbtool_config.h"
#endif
#include <sys/cdefs.h>
__RCSID("$NetBSD: expr.c,v 1.20 2019/03/26 16:39:50 christos Exp $");
#include <stdint.h>
#include <stdio.h>
#include <stddef.h>
#include "mdef.h"
#include "extern.h"

int32_t end_result;
const char *copy_toeval;

extern void yy_scan_string(const char *);
extern int yyparse(void);
extern int yyerror(const char *);

int
yyerror(const char *msg)
{
	fprintf(stderr, "m4:%s:%lu: %s in expr %s\n", infile[ilevel].name,
	    infile[ilevel].lineno, msg, copy_toeval);
	return(0);
}

int 
expr(const char *toeval)
{
	copy_toeval = toeval;
	yy_scan_string(toeval);
	yyparse();
	return end_result;
}
@


1.20
log
@print the source line and file where the error happened.
@
text
@d1 1
a1 1
/*	$NetBSD: expr.c,v 1.19 2009/10/26 21:11:28 christos Exp $	*/
d22 1
a22 1
__RCSID("$NetBSD: expr.c,v 1.19 2009/10/26 21:11:28 christos Exp $");
d39 1
a39 1
	fprintf(stderr, "m4:%s:%zu: %s in expr %s\n", infile[ilevel].name,
@


1.19
log
@resolve conflicts.
@
text
@d1 1
a1 1
/*	$NetBSD$	*/
d22 1
a22 1
__RCSID("$NetBSD$");
d39 2
a40 1
	fprintf(stderr, "m4: %s in expr %s\n", msg, copy_toeval);
@


1.19.46.1
log
@Sync with HEAD
@
text
@d1 1
a1 1
/*	$NetBSD: expr.c,v 1.21 2019/03/26 23:31:45 kre Exp $	*/
d22 1
a22 1
__RCSID("$NetBSD: expr.c,v 1.21 2019/03/26 23:31:45 kre Exp $");
d39 1
a39 2
	fprintf(stderr, "m4:%s:%lu: %s in expr %s\n", infile[ilevel].name,
	    infile[ilevel].lineno, msg, copy_toeval);
@


1.18
log
@exp() -> m4_exp().
@
text
@d1 2
a2 3
/*	$NetBSD: expr.c,v 1.17 2005/10/06 17:28:33 drochner Exp $	*/
/*	$OpenBSD: expr.c,v 1.11 2000/01/11 14:00:57 espie Exp $	*/

d4 1
a4 17
 * Copyright (c) 1989, 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * This code is derived from software contributed to Berkeley by
 * Ozan Yigit at York University.
 *
 * 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.
d6 11
a16 11
 * 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.
a17 1

a20 1

d22 3
a24 10
#if defined(__RCSID) && !defined(lint)
#if 0
static char sccsid[] = "@@(#)expr.c	8.2 (Berkeley) 4/29/95";
#else
__RCSID("$NetBSD: expr.c,v 1.17 2005/10/06 17:28:33 drochner Exp $");
#endif
#endif /* not lint */

#include <sys/types.h>
#include <ctype.h>
a25 1
#include <stdio.h>
d29 2
a30 36
/*
 *      expression evaluator: performs a standard recursive
 *      descent parse to evaluate any expression permissible
 *      within the following grammar:
 *
 *	expr	:	query EOS
 *	query	:	lor
 *		|	lor "?" query ":" query
 *	lor	:	land { "||" land }
 *	land	:	bor { "&&" bor }
 *	bor	:	xor { "|" xor }
 *	xor	:	band { "^" eqrel }
 *	band	:	eqrel { "&" eqrel }
 *	eqrel	:	nerel { ("==" | "!=") nerel }
 *	nerel	:	shift { ("<" | ">" | "<=" | ">=") shift }
 *	shift	:	primary { ("<<" | ">>") primary }
 *	primary	:	term { ("+" | "-") term }
 *	term	:	exp { ("*" | "/" | "%") exp }
 *	exp	:	unary { "**" unary }
 *	unary	:	factor
 *		|	("+" | "-" | "~" | "!") unary
 *	factor	:	constant
 *		|	"(" query ")"
 *	constant:	num
 *		|	"'" CHAR "'"
 *	num	:	DIGIT
 *		|	DIGIT num
 *
 *
 *      This expression evaluator is lifted from a public-domain
 *      C Pre-Processor included with the DECUS C Compiler distribution.
 *      It is hacked somewhat to be suitable for m4.
 *
 *      Originally by:  Mike Lutz
 *                      Bob Harper
 */
d32 3
a34 45
#define EQL     0
#define NEQ     1
#define LSS     2
#define LEQ     3
#define GTR     4
#define GEQ     5
#define OCTAL   8
#define DECIMAL 10
#define HEX	16

static const char *nxtch;		       /* Parser scan pointer */
static const char *where;

static int query(int);
static int lor(int);
static int land(int);
static int bor(int);
static int xor(int);
static int band(int);
static int eqrel(int);
static int nerel(int);
static int shift(int);
static int primary(int);
static int term(int);
static int m4_exp(int);
static int unary(int);
static int factor(int);
static int constant(int);
static int num(int);
static int skipws(void);
static void experr(const char *);

/*
 * For longjmp
 */
#include <setjmp.h>
static jmp_buf expjump;

/*
 * macros:
 *      ungetch - Put back the last character examined.
 *      getch   - return the next character from expr string.
 */
#define ungetch()       nxtch--
#define getch()         *nxtch++
d37 1
a37 23
expr(expbuf)
	const char *expbuf;
{
	int rval;

	nxtch = expbuf;
	where = expbuf;
	if (setjmp(expjump) != 0)
		return FALSE;

	rval = query(1);
	if (skipws() == EOS)
		return rval;

	printf("m4: ill-formed expression.\n");
	return FALSE;
}

/*
 * query : lor | lor '?' query ':' query
 */
static int
query(int mayeval)
d39 2
a40 14
	int bool, true_val, false_val;

	bool = lor(mayeval);
	if (skipws() != '?') {
		ungetch();
		return bool;
	}

	true_val = query(bool);
	if (skipws() != ':')
		experr("bad query: missing \":\"");

	false_val = query(!bool);
	return bool ? true_val : false_val;
d43 2
a44 438
/*
 * lor : land { '||' land }
 */
static int
lor(int mayeval)
{
	int c, vl, vr;

	vl = land(mayeval);
	while ((c = skipws()) == '|') {
		if (getch() != '|') {
			ungetch();
			break;
		}
		if (vl != 0)
			mayeval = 0;
		vr = land(mayeval);
		vl = vl || vr;
	}

	ungetch();
	return vl;
}

/*
 * land : not { '&&' not }
 */
static int
land(int mayeval)
{
	int c, vl, vr;

	vl = bor(mayeval);
	while ((c = skipws()) == '&') {
		if (getch() != '&') {
			ungetch();
			break;
		}
		if (vl == 0)
			mayeval = 0;
		vr = bor(mayeval);
		vl = vl && vr;
	}

	ungetch();
	return vl;
}

/*
 * bor : xor { "|" xor }
 */
static int
bor(int mayeval)
{
	int vl, vr, c, cr;

	vl = xor(mayeval);
	while ((c = skipws()) == '|') {
		cr = getch();
		ungetch();
		if (cr == '|')
			break;
		vr = xor(mayeval);
		vl |= vr;
	}
	ungetch();
	return (vl);
}

/*
 * xor : band { "^" band }
 */
static int
xor(int mayeval)
{
	int vl, vr, c;

	vl = band(mayeval);
	while ((c = skipws()) == '^') {
		vr = band(mayeval);
		vl ^= vr;
	}
	ungetch();
	return (vl);
}

/*
 * band : eqrel { "&" eqrel }
 */
static int
band(int mayeval)
{
	int c, cr, vl, vr;

	vl = eqrel(mayeval);
	while ((c = skipws()) == '&') {
		cr = getch();
		ungetch();
		if (cr == '&')
			break;
		vr = eqrel(mayeval);
		vl &= vr;
	}
	ungetch();
	return vl;
}

/*
 * eqrel : nerel { ("==" | "!=" ) nerel }
 */
static int
eqrel(int mayeval)
{
	int vl, vr, c, cr;

	vl = nerel(mayeval);
	while ((c = skipws()) == '!' || c == '=') {
		if ((cr = getch()) != '=') {
			ungetch();
			break;
		}
		vr = nerel(mayeval);
		switch (c) {
		case '=':
			vl = (vl == vr);
			break;
		case '!':
			vl = (vl != vr);
			break;
		}
	}
	ungetch();
	return vl;
}

/*
 * nerel : shift { ("<=" | ">=" | "<" | ">") shift }
 */
static int
nerel(int mayeval)
{
	int vl, vr, c, cr;

	vl = shift(mayeval);
	while ((c = skipws()) == '<' || c == '>') {
		if ((cr = getch()) != '=') {
			ungetch();
			cr = '\0';
		}
		vr = shift(mayeval);
		switch (c) {
		case '<':
			vl = (cr == '\0') ? (vl < vr) : (vl <= vr);
			break;
		case '>':
			vl = (cr == '\0') ? (vl > vr) : (vl >= vr);
			break;
		}
	}
	ungetch();
	return vl;
}

/*
 * shift : primary { ("<<" | ">>") primary }
 */
static int
shift(int mayeval)
{
	int vl, vr, c;

	vl = primary(mayeval);
	while (((c = skipws()) == '<' || c == '>') && getch() == c) {
		vr = primary(mayeval);

		if (c == '<')
			vl <<= vr;
		else
			vl >>= vr;
	}

	if (c == '<' || c == '>')
		ungetch();
	ungetch();
	return vl;
}

/*
 * primary : term { ("+" | "-") term }
 */
static int
primary(int mayeval)
{
	int c, vl, vr;

	vl = term(mayeval);
	while ((c = skipws()) == '+' || c == '-') {
		vr = term(mayeval);

		if (c == '+')
			vl += vr;
		else
			vl -= vr;
	}

	ungetch();
	return vl;
}

/*
 * term : exp { ("*" | "/" | "%") exp }
 */
static int
term(int mayeval)
{
	int c, vl, vr;

	vl = m4_exp(mayeval);
	while ((c = skipws()) == '*' || c == '/' || c == '%') {
		vr = m4_exp(mayeval);

		switch (c) {
		case '*':
			vl *= vr;
			break;
		case '/':
			if (!mayeval)
				/* short-circuit */;
			else if (vr == 0)
				errx(1, "division by zero in eval.");
			else
				vl /= vr;
			break;
		case '%':
			if (!mayeval)
				/* short-circuit */;
			else if (vr == 0)
				errx(1, "modulo zero in eval.");
			else
				vl %= vr;
			break;
		}
	}
	ungetch();
	return vl;
}

/*
 * exp : unary { "**" exp }
 */
static int
m4_exp(int mayeval)
{
	int c, vl, vr, n;

	vl = unary(mayeval);
	while ((c = skipws()) == '*') {
		if (getch() != '*') {
			ungetch();
			break;
		}
		vr = unary(mayeval);
		n = 1;
		while (vr-- > 0)
			n *= vl;
		return n;
	}

	ungetch();
	return vl;
}

/*
 * unary : factor | ("+" | "-" | "~" | "!") unary
 */
static int
unary(int mayeval)
{
	int val, c;

	if ((c = skipws()) == '+' || c == '-' || c == '~' || c == '!') {
		val = unary(mayeval);

		switch (c) {
		case '+':
			return val;
		case '-':
			return -val;
		case '~':
			return ~val;
		case '!':
			return !val;
		}
	}

	ungetch();
	return factor(mayeval);
}

/*
 * factor : constant | '(' query ')'
 */
static int
factor(int mayeval)
{
	int val;

	if (skipws() == '(') {
		val = query(mayeval);
		if (skipws() != ')')
			experr("bad factor: missing \")\"");
		return val;
	}

	ungetch();
	return constant(mayeval);
}

/*
 * constant: num | 'char'
 * Note: constant() handles multi-byte constants
 */
static int
constant(int mayeval)
{
	int i;
	int value;
	char c;
	int v[sizeof(int)];

	if (skipws() != '\'') {
		ungetch();
		return num(mayeval);
	}
	for (i = 0; i < sizeof(int); i++) {
		if ((c = getch()) == '\'') {
			ungetch();
			break;
		}
		if (c == '\\') {
			switch (c = getch()) {
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
				ungetch();
				c = num(mayeval);
				break;
			case 'n':
				c = 012;
				break;
			case 'r':
				c = 015;
				break;
			case 't':
				c = 011;
				break;
			case 'b':
				c = 010;
				break;
			case 'f':
				c = 014;
				break;
			}
		}
		v[i] = c;
	}
	if (i == 0 || getch() != '\'')
		experr("illegal character constant");
	for (value = 0; --i >= 0;) {
		value <<= 8;
		value += v[i];
	}
	return value;
}

/*
 * num : digit | num digit
 */
static int
num(int mayeval)
{
	int rval, c, base;
	int ndig;

	base = ((c = skipws()) == '0') ? OCTAL : DECIMAL;
	rval = 0;
	ndig = 0;
	if (base == OCTAL) {
		c = skipws();
		if (c == 'x' || c == 'X') {
			base = HEX;
			c = skipws();
		} else
			ndig++;
	}
	while ((base == HEX && isxdigit(c)) ||
			(c >= '0' && c <= (base == OCTAL ? '7' : '9'))) {
		rval *= base;
		if (isalpha(c))
			rval += (tolower(c) - 'a' + 10);
		else
			rval += (c - '0');
		c = getch();
		ndig++;
	}
	ungetch();

	if (ndig == 0)
		experr("bad constant");

	return rval;
}

/*
 * Skip over any white space and return terminating char.
 */
static int
skipws()
{
	char c;

	while ((c = getch()) <= ' ' && c > EOS)
		;
	return c;
}

/*
 * resets environment to eval(), prints an error 
 * and forces eval to return FALSE.
 */
static void
experr(msg)
	const char *msg;
d46 4
a49 2
	printf("m4: %s in expr %s.\n", msg, where);
	longjmp(expjump, -1);
@


1.17
log
@merge in FreeBSD's rev.1.14:
Fix m4 to properly handle bitwise operators &, ^, and |. Fix operator
precedence. Add short-circuit evaluation.
@
text
@d1 1
a1 1
/*	$NetBSD: expr.c,v 1.16 2004/06/20 22:20:15 jmc Exp $	*/
d45 1
a45 1
__RCSID("$NetBSD: expr.c,v 1.16 2004/06/20 22:20:15 jmc Exp $");
d117 1
a117 1
static int exp(int);
d397 1
a397 1
	vl = exp(mayeval);
d399 1
a399 1
		vr = exp(mayeval);
d431 1
a431 1
exp(int mayeval)
@


1.16
log
@Completely rework how tools/compat is done. Purge all uses/references to
_NETBSD_SOURCE as this makes cross building from older/newer versions of
NetBSD harder, not easier (and also makes the resulting tools 'different')

Wrap all required code with the inclusion of nbtool_config.h, attempt to
only use POSIX code in all places (or when reasonable test w. configure and
provide definitions: ala u_int, etc).

Reviewed by lukem. Tested on FreeBSD 4.9, Redhat Linux ES3, NetBSD 1.6.2 x86
NetBSD current (x86 and amd64) and Solaris 9.

Fixes PR's: PR#17762 PR#25944
@
text
@d1 1
a1 1
/*	$NetBSD: expr.c,v 1.15 2003/08/07 11:14:31 agc Exp $	*/
d45 1
a45 1
__RCSID("$NetBSD: expr.c,v 1.15 2003/08/07 11:14:31 agc Exp $");
d61 22
a82 29
 *      expr    :       query EOS
 *      query   :       lor
 *              |       lor "?" query ":" query
 *      lor     :       land { "||" land }
 *      land    :       not { "&&" not }
 *	not	:	eqrel
 *		|	'!' not
 *      eqrel   :       shift { eqrelop shift }
 *      shift   :       primary { shop primary }
 *      primary :       term { addop term }
 *      term    :       exp { mulop exp }
 *	exp	:	unary { expop unary }
 *      unary   :       factor
 *              |       unop unary
 *      factor  :       constant
 *              |       "(" query ")"
 *      constant:       num
 *              |       "'" CHAR "'"
 *      num     :       DIGIT
 *              |       DIGIT num
 *      shop    :       "<<"
 *              |       ">>"
 *      eqrel   :       "="
 *              |       "=="
 *              |       "!="
 *      	|       "<"
 *              |       ">"
 *              |       "<="
 *              |       ">="
d106 18
a123 16
static int query __P((void));
static int lor __P((void));
static int land __P((void));
static int not __P((void));
static int eqrel __P((void));
static int shift __P((void));
static int primary __P((void));
static int term __P((void));
static int exp __P((void));
static int unary __P((void));
static int factor __P((void));
static int constant __P((void));
static int num __P((void));
static int geteqrel __P((void));
static int skipws __P((void));
static void experr __P((const char *));
d150 1
a150 1
	rval = query();
d162 1
a162 1
query()
d166 1
a166 1
	bool = lor();
d172 1
a172 1
	true_val = query();
d174 1
a174 1
		experr("bad query");
d176 1
a176 1
	false_val = query();
d184 1
a184 1
lor()
d188 1
a188 1
	vl = land();
d190 1
a190 1
		if (getch() != '|')
d192 5
a196 1
		vr = land();
d208 1
a208 1
land()
d212 1
a212 1
	vl = not();
d214 1
a214 1
		if (getch() != '&')
d216 5
a220 1
		vr = not();
d229 1
a229 1
 * not : eqrel | '!' not
d232 1
a232 1
not()
d234 1
a234 1
	int val, c;
d236 3
a238 1
	if ((c = skipws()) == '!' && getch() != '=') {
d240 4
a243 2
		val = not();
		return !val;
d245 3
d249 13
a261 2
	if (c == '!')
		ungetch();
d263 1
a263 1
	return eqrel();
d267 1
a267 1
 * eqrel : shift { eqrelop shift }
d270 1
a270 1
eqrel()
d272 1
a272 1
	int vl, vr, eqrelvar;
d274 12
a285 3
	vl = shift();
	while ((eqrelvar = geteqrel()) != -1) {
		vr = shift();
d287 7
a293 1
		switch (eqrelvar) {
d295 9
a303 1
		case EQL:
d306 1
a306 1
		case NEQ:
d309 5
d315 18
a332 2
		case LEQ:
			vl = (vl <= vr);
d334 2
a335 8
		case LSS:
			vl = (vl < vr);
			break;
		case GTR:
			vl = (vl > vr);
			break;
		case GEQ:
			vl = (vl >= vr);
d339 1
d344 1
a344 1
 * shift : primary { shop primary }
d347 1
a347 1
shift()
d351 1
a351 1
	vl = primary();
d353 1
a353 1
		vr = primary();
d368 1
a368 1
 * primary : term { addop term }
d371 1
a371 1
primary()
d375 1
a375 1
	vl = term();
d377 1
a377 1
		vr = term();
d390 1
a390 1
 * <term> := <exp> { <mulop> <exp> }
d393 1
a393 1
term()
d397 1
a397 1
	vl = exp();
d399 1
a399 1
		vr = exp();
d406 3
a408 1
			if (vr == 0)
d414 3
a416 1
			if (vr == 0)
d428 1
a428 1
 * <term> := <unary> { <expop> <unary> }
d431 1
a431 1
exp()
d435 2
a436 4
	vl = unary();
	switch (c = skipws()) {

	case '*':
d441 1
a441 3

	case '^':
		vr = exp();
d453 1
a453 1
 * unary : factor | unop unary
d456 1
a456 1
unary()
d460 2
a461 2
	if ((c = skipws()) == '+' || c == '-' || c == '~') {
		val = unary();
d470 2
d476 1
a476 1
	return factor();
d483 1
a483 1
factor()
d488 1
a488 1
		val = query();
d490 1
a490 1
			experr("bad factor");
d495 1
a495 1
	return constant();
d503 1
a503 1
constant()
d512 1
a512 1
		return num();
d530 1
a530 1
				c = num();
d564 1
a564 1
num()
a598 44
 * eqrel : '=' | '==' | '!=' | '<' | '>' | '<=' | '>='
 */
static int
geteqrel()
{
	int c1, c2;

	c1 = skipws();
	c2 = getch();

	switch (c1) {

	case '=':
		if (c2 != '=')
			ungetch();
		return EQL;

	case '!':
		if (c2 == '=')
			return NEQ;
		ungetch();
		ungetch();
		return -1;

	case '<':
		if (c2 == '=')
			return LEQ;
		ungetch();
		return LSS;

	case '>':
		if (c2 == '=')
			return GEQ;
		ungetch();
		return GTR;

	default:
		ungetch();
		ungetch();
		return -1;
	}
}

/*
@


1.15
log
@Move UCB-licensed code from 4-clause to 3-clause licence.

Patches provided by Joel Baker in PR 22365, verified by myself.
@
text
@d1 1
a1 1
/*	$NetBSD: expr.c,v 1.14 2002/01/31 19:36:47 tv Exp $	*/
d36 4
d45 1
a45 1
__RCSID("$NetBSD: expr.c,v 1.14 2002/01/31 19:36:47 tv Exp $");
@


1.15.2.1
log
@Pull up revision 1.16 (requested by jmc in ticket #527):
Completely rework how tools/compat is done. Purge all uses/references to
_NETBSD_SOURCE as this makes cross building from older/newer versions of
NetBSD harder, not easier (and also makes the resulting tools 'different')
Wrap all required code with the inclusion of nbtool_config.h, attempt to
only use POSIX code in all places (or when reasonable test w. configure and
provide definitions: ala u_int, etc).
Reviewed by lukem. Tested on FreeBSD 4.9, Redhat Linux ES3, NetBSD 1.6.2 x86
NetBSD current (x86 and amd64) and Solaris 9.
Fixes PR's: PR#17762 PR#25944
@
text
@d1 1
a1 1
/*	$NetBSD$	*/
a35 4
#if HAVE_NBTOOL_CONFIG_H
#include "nbtool_config.h"
#endif

d41 1
a41 1
__RCSID("$NetBSD$");
@


1.14
log
@Protect __RCSID and __COPYRIGHT from being invoked if not defined.
@
text
@d1 1
a1 1
/*	$NetBSD: expr.c,v 1.13 2002/01/21 21:49:57 tv Exp $	*/
d19 1
a19 5
 * 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
d41 1
a41 1
__RCSID("$NetBSD: expr.c,v 1.13 2002/01/21 21:49:57 tv Exp $");
@


1.13
log
@Make compilable from src/tools/m4 on non-NetBSD hosts.
@
text
@d1 1
a1 1
/*	$NetBSD: expr.c,v 1.12 2001/11/14 06:16:08 tv Exp $	*/
d41 1
a41 1
#ifndef lint
d45 1
a45 1
__RCSID("$NetBSD: expr.c,v 1.12 2001/11/14 06:16:08 tv Exp $");
@


1.12
log
@Pull in various changes from OpenBSD, most from Marc Espie, including:
* Provide some GNUisms as extensions.
* Provide dynamically growable string space.
* Make define(defn(foo)) work correctly for builtins.
(The current version is supposed to be capable of satisfying autoconf.)

All still relevant NetBSD changes have been preserved in this version, and
formatting and style fixes have been applied in various places.

Thanks to Masao Uebayashi <uebayasi@@soum.co.jp> for pointing this out.
@
text
@d1 1
a1 1
/*	$NetBSD: expr.c,v 1.11 2001/03/05 20:26:17 wiz Exp $	*/
d45 1
a45 1
__RCSID("$NetBSD: expr.c,v 1.11 2001/03/05 20:26:17 wiz Exp $");
d49 1
a49 1
#include <sys/cdefs.h>
a50 1
#include <err.h>
@


1.11
log
@Sprinkle some const, and rename a shadow-variable.
@
text
@d1 2
a2 1
/*	$NetBSD: expr.c,v 1.10 2000/10/17 18:51:32 jdolecek Exp $	*/
d45 1
a45 1
__RCSID("$NetBSD: expr.c,v 1.10 2000/10/17 18:51:32 jdolecek Exp $");
d50 3
a53 2
#include <ctype.h>

a100 3
#define TRUE    1
#define FALSE   0
#define EOS     (char) 0
d111 2
a112 1
static char *nxtch;		       /* Parser scan pointer */
d147 1
a147 1
	char *expbuf;
d152 1
d347 4
a350 1
			vl /= vr;
d353 4
a356 1
			vl %= vr;
a534 1

d602 1
a602 1
	printf("m4: %s in expr.\n", msg);
@


1.10
log
@Fix unconsistent spacing/tabs. Adresses bin/11158 by Nathan Ahlstrom.
@
text
@d1 1
a1 1
/*	$NetBSD: expr.c,v 1.9 1999/04/14 09:38:37 matthias Exp $	*/
d44 1
a44 1
__RCSID("$NetBSD: expr.c,v 1.9 1999/04/14 09:38:37 matthias Exp $");
d129 1
a129 1
static void experr __P((char *));
d251 1
a251 1
	int vl, vr, eqrel;
d254 1
a254 1
	while ((eqrel = geteqrel()) != -1) {
d257 1
a257 1
		switch (eqrel) {
d594 1
a594 1
	char *msg;
@


1.9
log
@make eval() recognize hexadecimal constant as specified in the man page.
@
text
@d1 1
a1 1
/*	$NetBSD: expr.c,v 1.8 1997/10/19 04:39:53 lukem Exp $	*/
d44 1
a44 1
__RCSID("$NetBSD: expr.c,v 1.8 1997/10/19 04:39:53 lukem Exp $");
d523 1
a523 1
	
d526 1
a526 1
	
@


1.8
log
@WARNSify, fix .Nm usage, getopt returns -1 not EOF, deprecate register
@
text
@d1 1
a1 1
/*	$NetBSD: expr.c,v 1.7 1995/09/28 05:37:31 tls Exp $	*/
d44 1
a44 1
__RCSID("$NetBSD$");
d50 1
d110 1
d504 10
a513 1
	while (c >= '0' && c <= (base == OCTAL ? '7' : '9')) {
d515 4
a518 1
		rval += (c - '0');
@


1.8.4.1
log
@Pull up revision 1.9 from trunk (recognize hexadecimal constants in eval()).
@
text
@d1 1
a1 1
/*	$NetBSD: expr.c,v 1.8 1997/10/19 04:39:53 lukem Exp $	*/
d44 1
a44 1
__RCSID("$NetBSD: expr.c,v 1.8 1997/10/19 04:39:53 lukem Exp $");
a49 1
#include <ctype.h>
a108 1
#define HEX	16
d502 1
a502 10
	if (base == OCTAL) {
		c = skipws();
		if (c == 'x' || c == 'X') {
			base = HEX;
			c = skipws();
		} else
			ndig++;
	}
	while ((base == HEX && isxdigit(c)) ||
			(c >= '0' && c <= (base == OCTAL ? '7' : '9'))) {
d504 1
a504 4
		if (isalpha(c))
			rval += (tolower(c) - 'a' + 10);
		else
			rval += (c - '0');
@


1.7
log
@Sync with 4.4BSD-Lite2
@
text
@d1 1
a1 1
/*	$NetBSD: $	*/
d39 1
d44 1
a44 1
static char rcsid[] = "$NetBSD: $";
d51 3
d145 1
a145 1
char *expbuf;
d147 1
a147 1
	register int rval;
d167 1
a167 1
	register int bool, true_val, false_val;
d189 1
a189 1
	register int c, vl, vr;
d209 1
a209 1
	register int c, vl, vr;
d229 1
a229 1
	register int val, c;
d249 1
a249 1
	register int vl, vr, eqrel;
d287 1
a287 1
	register int vl, vr, c;
d311 1
a311 1
	register int c, vl, vr;
d333 1
a333 1
	register int c, vl, vr;
d361 1
a361 1
	register c, vl, vr, n;
d390 1
a390 1
	register int val, c;
d415 1
a415 1
	register int val;
d435 3
a437 3
	register int i;
	register int value;
	register char c;
d496 1
a496 1
	register int rval, c, base;
d523 1
a523 1
	register int c1, c2;
d567 1
a567 1
	register char c;
d580 1
a580 1
char *msg;
@


1.6
log
@There were several places where m4 did not conform to the specification
in `The M4 Macro Processor', by Kernighan and Ritchie.

* `|' and `||' are both logical or.  There is no binary or.
* `&' and `&&' are both logical and.  There is no binary and.
* `!' has a much higher precedence.
* The equal and relation operators have the same precedence.
* `**' is implemented, and `^' is for exponentation (not xor).
* Unary `+' in implemented.

I've coded exponentiation to return what appears to be the same results
that other versions of m4 return.
@
text
@d1 2
d40 5
a44 1
static char sccsid[] = "@@(#)expr.c	8.1 (Berkeley) 6/6/93";
@


1.5
log
@upgrade to 4.4-lite m4.  no local changes of note
@
text
@d53 4
a56 6
 *      land    :       bor { "&&" bor }
 *      bor     :       bxor { "|" bxor }
 *      bxor    :       band { "^" band }
 *      band    :       eql { "&" eql }
 *      eql     :       relat { eqrel relat }
 *      relat   :       shift { rel shift }
d59 2
a60 1
 *      term    :       unary { mulop unary }
d71 1
a71 1
 *      eqlrel  :       "="
d74 1
a74 1
 *      rel     :       "<"
d105 2
a106 5
static int bor __P((void));
static int bxor __P((void));
static int band __P((void));
static int eql __P((void));
static int relat __P((void));
d110 1
d115 1
a115 2
static int geteql __P((void));
static int getrel __P((void));
d182 3
a184 1
	while ((c = skipws()) == '|' && getch() == '|') {
a188 2
	if (c == '|')
		ungetch();
d194 1
a194 1
 * land : bor { '&&' bor }
d201 5
a205 3
	vl = bor();
	while ((c = skipws()) == '&' && getch() == '&') {
		vr = bor();
a208 2
	if (c == '&')
		ungetch();
d214 1
a214 1
 * bor : bxor { '|' bxor }
d217 1
a217 1
bor()
d219 1
a219 1
	register int vl, vr, c;
d221 1
a221 2
	vl = bxor();
	while ((c = skipws()) == '|' && getch() != '|') {
d223 2
a224 2
		vr = bxor();
		vl |= vr;
d227 1
a227 1
	if (c == '|')
d230 1
a230 1
	return vl;
d234 1
a234 1
 * bxor : band { '^' band }
d237 1
a237 1
bxor()
d239 1
a239 1
	register int vl, vr;
d241 3
a243 38
	vl = band();
	while (skipws() == '^') {
		vr = band();
		vl ^= vr;
	}

	ungetch();
	return vl;
}

/*
 * band : eql { '&' eql }
 */
static int
band()
{
	register int vl, vr, c;

	vl = eql();
	while ((c = skipws()) == '&' && getch() != '&') {
		ungetch();
		vr = eql();
		vl &= vr;
	}

	if (c == '&')
		ungetch();
	ungetch();
	return vl;
}

/*
 * eql : relat { eqrel relat }
 */
static int
eql()
{
	register int vl, vr, rel;
d245 1
a245 5
	vl = relat();
	while ((rel = geteql()) != -1) {
		vr = relat();

		switch (rel) {
a252 18
		}
	}
	return vl;
}

/*
 * relat : shift { rel shift }
 */
static int
relat()
{
	register int vl, vr, rel;

	vl = shift();
	while ((rel = getrel()) != -1) {

		vr = shift();
		switch (rel) {
d280 1
a280 1
	while (((c = skipws()) == '<' || c == '>') && c == getch()) {
d306 1
d318 1
a318 1
 * <term> := <unary> { <mulop> <unary> }
d325 1
a325 1
	vl = unary();
d327 1
a327 1
		vr = unary();
d346 29
d382 1
a382 1
	if ((c = skipws()) == '!' || c == '~' || c == '-') {
d386 4
a389 2
		case '!':
			return !val;
a391 2
		case '-':
			return -val;
d508 1
a508 1
 * eqlrel : '=' | '==' | '!='
d511 1
a511 1
geteql()
a530 20

	default:
		ungetch();
		ungetch();
		return -1;
	}
}

/*
 * rel : '<' | '>' | '<=' | '>='
 */
static int
getrel()
{
	register int c1, c2;

	c1 = skipws();
	c2 = getch();

	switch (c1) {
@


1.4
log
@latest m4 from ozan.  now does the right thing w/respect to sendmail
@
text
@d1 39
a39 68
/*  File   : expr.c
    Authors: Mike Lutz & Bob Harper
    Editors: Ozan Yigit & Richard A. O'Keefe
    Updated: %G%
    Purpose: arithmetic expression evaluator.

    expr() performs a standard recursive descent parse to evaluate any
    expression permitted byf the following grammar:

      expr    :       query EOS
      query   :       lor
              |       lor "?" query ":" query
      lor     :       land { "||" land }	or OR,  for Pascal
      land    :       bor { "&&" bor }		or AND, for Pascal
      bor     :       bxor { "|" bxor }
      bxor    :       band { "^" band }
      band    :       eql { "&" eql }
      eql     :       relat { eqrel relat }
      relat   :       shift { rel shift }
      shift   :       primary { shop primary }
      primary :       term { addop term }
      term    :       unary { mulop unary }
      unary   :       factor
              |       unop unary
      factor  :       constant
              |       "(" query ")"
      constant:       num
              |       "'" CHAR "'"		or '"' CHAR '"'
      num     :       DIGIT			full ANSI C syntax
              |       DIGIT num
      shop    :       "<<"
              |       ">>"
      eqlrel  :       "="
              |       "=="
              |       "!="
      rel     :       "<"			or <>, Pascal not-equal
              |       ">"
              |       "<="			or =<, for Prolog users.
              |       ">="

    This expression evaluator was lifted from a public-domain
    C Pre-Processor included with the DECUS C Compiler distribution.
    It has been hacked somewhat to be suitable for m4.

    26-Mar-1993		Changed to work in any of EBCDIC, ASCII, DEC MNCS,
			or ISO 8859/n.

    26-Mar-1993		Changed to use "long int" rather than int, so that
			we get the same 32-bit arithmetic on a PC as on a Sun.
			It isn't fully portable, of course, but then on a 64-
			bit machine we _want_ 64-bit arithmetic...
			Shifting rewritten (using LONG_BIT) to give signed
			shifts even when (long) >> (long) is unsigned.

    26-Mar-1993		I finally got sick of the fact that &&, ||, and ?:
			don't do conditional evaluation.  What is the good
			of having eval(0&&(1/0)) crash and dump core?  Now
			every function has a doit? argument.

    26-Mar-1993		charcon() didn't actually accept 'abcd', which it
			should have.  Fixed it.

    20-Apr-1993		eval(1/0) and eval(1%0) dumped core and crashed.
			This is also true of the System V r 3.2 m4, but
			it isn't good enough for ours!  Changed it so that
			x % 0 => x	as per Concrete Mathematics
			x / 0 => error and return 0 from expr().
*/
d41 49
d91 37
a127 1
#define	TRUE	1
d129 47
a175 3
#include <stdio.h>
#include <setjmp.h>
static jmp_buf expjump;		/* Error exit point for expr() */
d177 19
a195 1
static unsigned char *nxtchr;	/* Parser scan pointer */
d197 19
a215 156
#define	deblank0	while ((unsigned)(*nxtchr-1) < ' ') nxtchr++
#define deblank1	while ((unsigned)(*++nxtchr - 1) < ' ')
#define deblank2	nxtchr++; deblank1

#include "ourlims.h"
static char digval[1+UCHAR_MAX];

/*  This file should work in any C implementation that doesn't have too
    many characters to fit in one table.  We use a table to convert
    (unsigned) characters to numeric codes:
	 0 to  9	for '0' to '9'
	10 to 35	for 'a' to 'z'
	10 to 35	for 'A' to 'Z'
	36		for '_'
    Instead of asking whether tolower(c) == 'a' we ask whether
    digval[c] == DIGIT_A, and so on.  This essentially duplicates the
    chtype[] table in main.c; we should use just one table.
*/
#define	DIGIT_A 10
#define	DIGIT_B 11
#define	DIGIT_C 12
#define	DIGIT_D 13
#define	DIGIT_E 14
#define	DIGIT_F 15
#define	DIGIT_G 16
#define DIGIT_H 17
#define	DIGIT_I	18
#define	DIGIT_J 19
#define DIGIT_K 20
#define	DIGIT_L	21
#define DIGIT_M 22
#define DIGIT_N 23
#define	DIGIT_O 24
#define	DIGIT_P 25
#define	DIGIT_Q 26
#define	DIGIT_R	27
#define	DIGIT_S 28
#define	DIGIT_T 29
#define	DIGIT_U 30
#define	DIGIT_V 31
#define	DIGIT_W 32
#define	DIGIT_X 33
#define	DIGIT_Y 34
#define	DIGIT_Z 35


#ifdef	__STDC__
static long int query(int);
#else
static long int query();
#endif


/*  experr(msg)
    prints an error message, resets environment to expr(), and
    forces expr() to return FALSE.
*/
void experr(msg)
    char *msg;
    {
	(void) fprintf(stderr, "m4: %s\n", msg);
	longjmp(expjump, -1);	/* Force expr() to return FALSE */
    }


/*  <numcon> ::= '0x' <hex> | '0X' <hex> | '0' <oct> | <dec>
    For ANSI C, an integer may be followed by u, l, ul, or lu,
    in any mix of cases.  We accept and ignore those letters;
    all the numbers are treated as long.
*/
static long int numcon(doit)
    int doit;
    {
	register long int v;	/* current value */
	register int b;		/* base (radix) */
	register int c;		/* character or digit value */

	if (!doit) {
	    do nxtchr++; while (digval[*nxtchr] <= 36);
	    deblank0;
	    return 0;
	}

	v = digval[*nxtchr++];	/* We already know it's a digit */
	if (v != 0) {
	    b = 10;		/* decimal number */
	} else
	if (digval[*nxtchr] == DIGIT_X) {
	    nxtchr++;
	    b = 16;		/* hexadecimal number */
	} else {
	    b = 8;		/* octal number */
	}
	do {
	    while (digval[c = *nxtchr++] < b) v = v*b + digval[c];
	} while (c == '_');
	while (digval[c] == DIGIT_L || digval[c] == DIGIT_U) c = *nxtchr++;
	nxtchr--;		/* unread c */
	if ((unsigned)(c-1) < ' ') { deblank1; }
	return v;
    }


/*  <charcon> ::= <qt> { <char> } <qt>
    Note: multibyte constants are accepted.
    Note: BEL (\a) and ESC (\e) have the same values in EBCDIC and ASCII.
*/
static long int charcon(doit)
    int doit;
    {
	register int i;
	long int value;
	register int c;
	int q;
	int v[sizeof value];

	q = *nxtchr++;		/* the quote character */
	for (i = 0; ; i++) {
	    c = *nxtchr++;
	    if (c == q) {	/* end of literal, or doubled quote */
		if (*nxtchr != c) break;
		nxtchr++;	/* doubled quote stands for one quote */
	    }
	    if (i == sizeof value) experr("Unterminated character constant");
	    if (c == '\\') {
		switch (c = *nxtchr++) {
		    case '0': case '1': case '2': case '3':
		    case '4': case '5': case '6': case '7':
			c -= '0';
			if ((unsigned)(*nxtchr - '0') < 8)
			    c = (c << 3) | (*nxtchr++ - '0');
			if ((unsigned)(*nxtchr - '0') < 8)
			    c = (c << 3) | (*nxtchr++ - '0');
			break;
		    case 'n': case 'N': c = '\n'; break;
		    case 'r': case 'R': c = '\r'; break;
		    case 't': case 'T': c = '\t'; break;
		    case 'b': case 'B': c = '\b'; break;
		    case 'f': case 'F': c = '\f'; break;
		    case 'a': case 'A': c = 007;  break;
		    case 'e': case 'E': c = 033;  break;
#if	' ' == 64
		    case 'd': case 'D': c = 045;  break; /*EBCDIC DEL */
#else
		    case 'd': case 'D': c = 127;  break; /* ASCII DEL */
#endif
		    default :			  break;
		}
	    }
	    v[i] = c;
	}
	deblank0;
	if (!doit) return 0;
	for (value = 0; --i >= 0; ) value = (value << CHAR_BIT) | v[i];
	return value;
    }
d217 20
d238 12
a249 143
/*  <unary> ::= <unop> <unary> | <factor>
    <unop> ::= '!' || '~' | '-'
    <factor> ::= '(' <query> ')' | <'> <char> <'> | <"> <char> <"> | <num>
*/
static long int unary(doit)
    int doit;
    {
	long int v;

	switch (nxtchr[0]) {
	    case 'n': case 'N':
			if (digval[nxtchr[1]] != DIGIT_O
			||  digval[nxtchr[2]] != DIGIT_T)
			    experr("Bad 'not'");
			nxtchr += 2;
	    case '!':	deblank1; return !unary(doit);
	    case '~':	deblank1; return ~unary(doit);
	    case '-':	deblank1; return -unary(doit);
	    case '+':	deblank1; return  unary(doit);
	    case '(':	deblank1; v = query(doit);
			if (nxtchr[0] != ')') experr("Bad factor");
			deblank1; return v;
	    case '\'':
	    case '\"':	return charcon(doit);
	    case '0': case '1': case '2':
	    case '3': case '4': case '5':
	    case '6': case '7': case '8':
	    case '9':	return numcon(doit);
	    default :   experr("Bad constant");
	}
	return 0;	/*NOTREACHED*/
    }


/*  <term> ::= <unary> { <mulop> <unary> }
    <mulop> ::= '*' | '/' || '%'
*/
static long int term(doit)
    int doit;
    {
	register long int vl, vr;

	vl = unary(doit);
	for (;;)
	    switch (nxtchr[0]) {
		case '*':
		    deblank1;
		    vr = unary(doit);
		    if (doit) vl *= vr;
		    break;
		case 'd': case 'D':
		    if (digval[nxtchr[1]] != DIGIT_I
		    ||  digval[nxtchr[2]] != DIGIT_V)
			experr("Bad 'div'");
		    nxtchr += 2;
		    /*FALLTHROUGH*/
		case '/':
		    deblank1;
		    vr = unary(doit);
		    if (doit) {
			if (vr == 0) experr("Division by 0");
			vl /= vr;
		    }
		    break;
		case 'm': case 'M':
		    if (digval[nxtchr[1]] != DIGIT_O
		    ||  digval[nxtchr[2]] != DIGIT_D)
			experr("Bad 'mod'");
		    nxtchr += 2;
		    /*FALLTHROUGH*/
		case '%':
		    deblank1;
		    vr = unary(doit);
		    if (doit) {
			if (vr != 0) vl %= vr;
		    }
		    break;
		default:
		    return vl;
	    }
	/*NOTREACHED*/
    }

/*  <primary> ::= <term> { <addop> <term> }
    <addop> ::= '+' | '-'
*/
static long int primary(doit)
    int doit;
    {
	register long int vl;

	vl = term(doit);
	for (;;)
	    if (nxtchr[0] == '+') {
		deblank1;
		if (doit) vl += term(doit); else (void)term(doit);
	    } else
	    if (nxtchr[0] == '-') {
		deblank1;
		if (doit) vl -= term(doit); else (void)term(doit);
	    } else
		return vl;
	/*NOTREACHED*/
    }


/*  <shift> ::= <primary> { <shop> <primary> }
    <shop> ::= '<<' | '>>'
*/
static long int shift(doit)
    int doit;
    {
	register long int vl, vr;

	vl = primary(doit);
	for (;;) {
	    if (nxtchr[0] == '<' && nxtchr[1] == '<') {
		deblank2;
		vr = primary(doit);
	    } else
	    if (nxtchr[0] == '>' && nxtchr[1] == '>') {
		deblank2;
		vr = -primary(doit);
	    } else {
		return vl;
	    }
	    /* The following code implements shifts portably */
	    /* Shifts are signed shifts, and the shift count */
	    /* acts like repeated one-bit shifts, not modulo anything */
	    if (doit) {
		if (vr >= LONG_BIT) {
		    vl = 0;
		} else
		if (vr <= -LONG_BIT) {
		    vl = -(vl < 0);
		} else
		if (vr > 0) {
		    vl <<= vr;
		} else
		if (vr < 0) {
		    vl = (vl >> -vr) | (-(vl < 0) << (LONG_BIT + vr));
		}
	    }
a250 2
	/*NOTREACHED*/
    }
d252 3
d256 18
a273 94
/*  <relat> ::= <shift> { <rel> <shift> }
    <rel> ::= '<=' | '>=' | '=<' | '=>' | '<' | '>'
    Here I rely on the fact that '<<' and '>>' are swallowed by <shift>
*/
static long int relat(doit)
    int doit;
    {
	register long int vl;

	vl = shift(doit);
	for (;;)
	    switch (nxtchr[0]) {
		case '=':
		    switch (nxtchr[1]) {
			case '<':			/* =<, take as <= */
			    deblank2;
			    vl = vl <= shift(doit);
			    break;
			case '>':			/* =>, take as >= */
			    deblank2;
			    vl = vl >= shift(doit);
			    break;
			default:			/* == or =; OOPS */
			    return vl;
		    }
		    break;
		case '<':
		    if (nxtchr[1] == '=') {		/* <= */
			deblank2;
			vl = vl <= shift(doit);
		    } else
		    if (nxtchr[1] == '>') {		/* <> (Pascal) */
			deblank2;
			vl = vl != shift(doit);
		    } else {				/* < */
			deblank1;
			vl = vl < shift(doit);
		    }
		    break;
		case '>':
		    if (nxtchr[1] == '=') {		/* >= */
			deblank2;
			vl = vl >= shift(doit);
		    } else {				/* > */
			deblank1;
			vl = vl > shift(doit);
		    }
		    break;
		default:
		    return vl;
	}
	/*NOTREACHED*/
    }


/*  <eql> ::= <relat> { <eqrel> <relat> }
    <eqlrel> ::= '!=' | '==' | '='
*/
static long int eql(doit)
    int doit;
    {
	register long int vl;

	vl = relat(doit);
	for (;;)
	    if (nxtchr[0] == '!' && nxtchr[1] == '=') {
		deblank2;
		vl = vl != relat(doit);
	    } else
	    if (nxtchr[0] == '=' && nxtchr[1] == '=') {
		deblank2;
		vl = vl == relat(doit);
	    } else
	    if (nxtchr[0] == '=') {
		deblank1;
		vl = vl == relat(doit);
	    } else
		return vl;
	/*NOTREACHED*/
    }


/*  <band> ::= <eql> { '&' <eql> }
*/
static long int band(doit)
    int doit;
    {
	register long int vl;

	vl = eql(doit);
	while (nxtchr[0] == '&' && nxtchr[1] != '&') {
	    deblank1;
	    if (doit) vl &= eql(doit); else (void)eql(doit);
	}
d275 1
a275 1
    }
d277 11
d289 9
a297 11
/*  <bxor> ::= <band> { '^' <band> }
*/
static long int bxor(doit)
    int doit;
    {
	register long int vl;

	vl = band(doit);
	while (nxtchr[0] == '^') {
	    deblank1;
	    if (doit) vl ^= band(doit); else (void)band(doit);
d300 9
a308 1
    }
d310 2
d313 16
a328 11
/*  <bor> ::= <bxor> { '|' <bxor> }
*/
static long int bor(doit)
    int doit;
    {
	register long int vl;

	vl = bxor(doit);
	while (nxtchr[0] == '|' && nxtchr[1] != '|') {
	    deblank1;
	    if (doit) vl |= bxor(doit); else (void)bxor(doit);
d331 1
a331 1
    }
d333 23
d357 15
a371 22
/*  <land> ::= <bor> { '&&' <bor> }
*/
static long int land(doit)
    int doit;
    {
	register long int vl;

	vl = bor(doit);
	for (;;) {
	    if (nxtchr[0] == '&') {
		if (nxtchr[1] != '&') break;
		deblank2;
	    } else
	    if (digval[nxtchr[0]] == DIGIT_A) {
		if (digval[nxtchr[1]] != DIGIT_N) break;
		if (digval[nxtchr[2]] != DIGIT_D) break;
		nxtchr += 2; deblank1;
	    } else {
		/* neither && nor and */
		break;
	    }
	    vl = bor(doit && vl) != 0;
d373 2
d376 1
a376 1
    }
d378 11
d390 11
a400 20
/*  <lor> ::= <land> { '||' <land> }
*/
static long int lor(doit)
    int doit;
    {
	register long int vl;

	vl = land(doit);
	for (;;) {
	    if (nxtchr[0] == '|') {
		if (nxtchr[1] != '|') break;
	    } else
	    if (digval[nxtchr[0]] == DIGIT_O) {
		if (digval[nxtchr[1]] != DIGIT_R) break;
	    } else {
		/* neither || nor or */
		break;
	    }
	    deblank2;
	    vl = land(doit && !vl) != 0;
d402 1
d404 1
a404 1
    }
d406 20
d427 84
a510 16
/*  <query> ::= <lor> [ '?' <query> ':' <query> ]
*/
static long int query(doit)
    int doit;
    {
	register long int bool, true_val, false_val;

	bool = lor(doit);
	if (*nxtchr != '?') return bool;
	deblank1;
	true_val = query(doit && bool);
	if (*nxtchr != ':') experr("Bad query");
	deblank1;
	false_val = query(doit && !bool);
	return bool ? true_val : false_val;
    }
d512 24
d537 1
a537 32
static void initialise_digval()
    {
	register unsigned char *s;
	register int c;

	for (c = 0; c <= UCHAR_MAX; c++) digval[c] = 99;
	for (c =  0, s = (unsigned char *)"0123456789";
	/*while*/ *s;
	/*doing*/ digval[*s++] = c++) /* skip */;
	for (c = 10, s = (unsigned char *)"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
	/*while*/ *s;
	/*doing*/ digval[*s++] = c++) /* skip */;
	for (c = 10, s = (unsigned char *)"abcdefghijklmnopqrstuvwxyz";
	/*while*/ *s;
	/*doing*/ digval[*s++] = c++) /* skip */;
	digval['_'] = 36;
    }


long int expr(expbuf)
    char *expbuf;
    {
	register int rval;

	if (digval['1'] == 0) initialise_digval();
	nxtchr = (unsigned char *)expbuf;
	deblank0;
	if (setjmp(expjump) != 0) return FALSE;
	rval = query(TRUE);
	if (*nxtchr) experr("Ill-formed expression");
	return rval;
    }
d539 88
@


1.3
log
@Add RCS identifiers, remove some completely useless RCS logs and patchkit
headers, and a few other insignificant changes.
@
text
@a69 4
#ifndef lint
static char rcsid[] = "$Id: $";
#endif /* not lint */

@


1.2
log
@baseline of new version of m4 supplied by Ozan Yigit, original author
of the broken m4 we had.  This is his stuff virgin + our Makefile.
@
text
@d70 4
@


1.1
log
@Initial revision
@
text
@d1 5
a5 39
/*
 * Copyright (c) 1989 The Regents of the University of California.
 * All rights reserved.
 *
 * This code is derived from software contributed to Berkeley by
 * Ozan Yigit.
 *
 * 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 char sccsid[] = "@@(#)expr.c	5.3 (Berkeley) 2/26/91";
#endif /* not lint */
d7 67
d75 542
a616 1
#include <stdio.h>
a617 557
/*
 *      expression evaluator: performs a standard recursive
 *      descent parse to evaluate any expression permissible
 *      within the following grammar:
 *
 *      expr    :       query EOS
 *      query   :       lor
 *              |       lor "?" query ":" query
 *      lor     :       land { "||" land }
 *      land    :       bor { "&&" bor }
 *      bor     :       bxor { "|" bxor }
 *      bxor    :       band { "^" band }
 *      band    :       eql { "&" eql }
 *      eql     :       relat { eqrel relat }
 *      relat   :       shift { rel shift }
 *      shift   :       primary { shop primary }
 *      primary :       term { addop term }
 *      term    :       unary { mulop unary }
 *      unary   :       factor
 *              |       unop unary
 *      factor  :       constant
 *              |       "(" query ")"
 *      constant:       num
 *              |       "'" CHAR "'"
 *      num     :       DIGIT
 *              |       DIGIT num
 *      shop    :       "<<"
 *              |       ">>"
 *      eqlrel  :       "="
 *              |       "=="
 *              |       "!="
 *      rel     :       "<"
 *              |       ">"
 *              |       "<="
 *              |       ">="
 *
 *
 *      This expression evaluator is lifted from a public-domain
 *      C Pre-Processor included with the DECUS C Compiler distribution.
 *      It is hacked somewhat to be suitable for m4.
 *
 *      Originally by:  Mike Lutz
 *                      Bob Harper
 */
 
#define TRUE    1
#define FALSE   0
#define EOS     (char) 0
#define EQL     0
#define NEQ     1
#define LSS     2
#define LEQ     3
#define GTR     4
#define GEQ     5
#define OCTAL   8
#define DECIMAL 10
 
static char *nxtch;     /* Parser scan pointer */
 
/*
 * For longjmp
 */
static jmp_buf  expjump;
 
/*
 * macros:
 *
 *      ungetch - Put back the last character examined.
 *      getch   - return the next character from expr string.
 */
#define ungetch()       nxtch--
#define getch()         *nxtch++
 
expr(expbuf)
char *expbuf;
{
        register int rval;
 
        nxtch = expbuf;
        if (setjmp(expjump) != 0)
                return (FALSE);
        rval = query();
        if (skipws() == EOS)
                return(rval);
        experr("Ill-formed expression");
}
 
/*
 * query : lor | lor '?' query ':' query
 *
 */
query()
{
        register int bool, true_val, false_val;
 
        bool = lor();
        if (skipws() != '?') {
                ungetch();
                return(bool);
        }
 
        true_val = query();
        if (skipws() != ':')
                experr("Bad query");
 
        false_val = query();
        return(bool ? true_val : false_val);
}
 
/*
 * lor : land { '||' land }
 *
 */
lor()
{
        register int c, vl, vr;
 
        vl = land();
        while ((c = skipws()) == '|' && getch() == '|') {
                vr = land();
                vl = vl || vr;
        }
 
        if (c == '|')
                ungetch();
        ungetch();
        return(vl);
}
 
/*
 * land : bor { '&&' bor }
 *
 */
land()
{
        register int c, vl, vr;
 
        vl = bor();
        while ((c = skipws()) == '&' && getch() == '&') {
                vr = bor();
                vl = vl && vr;
        }
 
        if (c == '&')
                ungetch();
        ungetch();
        return(vl);
}
 
/*
 * bor : bxor { '|' bxor }
 *
 */
bor()
{
        register int vl, vr, c;
 
        vl = bxor();
        while ((c = skipws()) == '|' && getch() != '|') {
                ungetch();
                vr = bxor();
                vl |= vr;
        }
 
        if (c == '|')
                ungetch();
        ungetch();
        return(vl);
}
 
/*
 * bxor : band { '^' band }
 *
 */
bxor()
{
        register int vl, vr;
 
        vl = band();
        while (skipws() == '^') {
                vr = band();
                vl ^= vr;
        }
 
        ungetch();
        return(vl);
}
 
/*
 * band : eql { '&' eql }
 *
 */
band()
{
        register int vl, vr, c;
 
        vl = eql();
        while ((c = skipws()) == '&' && getch() != '&') {
                ungetch();
                vr = eql();
                vl &= vr;
        }
 
        if (c == '&')
                ungetch();
        ungetch();
        return(vl);
}
 
/*
 * eql : relat { eqrel relat }
 *
 */
eql()
{
        register int vl, vr, rel;
 
        vl = relat();
        while ((rel = geteql()) != -1) {
                vr = relat();
 
                switch (rel) {
 
                case EQL:
                        vl = (vl == vr);
                        break;
                case NEQ:
                        vl = (vl != vr);
                        break;
                }
        }
        return(vl);
}
 
/*
 * relat : shift { rel shift }
 *
 */
relat()
{
        register int vl, vr, rel;
 
        vl = shift();
        while ((rel = getrel()) != -1) {
 
                vr = shift();
                switch (rel) {
 
                case LEQ:
                        vl = (vl <= vr);
                        break;
                case LSS:
                        vl = (vl < vr);
                        break;
                case GTR:
                        vl = (vl > vr);
                        break;
                case GEQ:
                        vl = (vl >= vr);
                        break;
                }
        }
        return(vl);
}
 
/*
 * shift : primary { shop primary }
 *
 */
shift()
{
        register int vl, vr, c;
 
        vl = primary();
        while (((c = skipws()) == '<' || c == '>') && c == getch()) {
                vr = primary();
 
                if (c == '<')
                        vl <<= vr;
                else
                        vl >>= vr;
        }
 
        if (c == '<' || c == '>')
                ungetch();
        ungetch();
        return(vl);
}
 
/*
 * primary : term { addop term }
 *
 */
primary()
{
        register int c, vl, vr;
 
        vl = term();
        while ((c = skipws()) == '+' || c == '-') {
                vr = term();
                if (c == '+')
                        vl += vr;
                else
                        vl -= vr;
        }
 
        ungetch();
        return(vl);
}
 
/*
 * <term> := <unary> { <mulop> <unary> }
 *
 */
term()
{
        register int c, vl, vr;
 
        vl = unary();
        while ((c = skipws()) == '*' || c == '/' || c == '%') {
                vr = unary();
 
                switch (c) {
                case '*':
                        vl *= vr;
                        break;
                case '/':
                        vl /= vr;
                        break;
                case '%':
                        vl %= vr;
                        break;
                }
        }
        ungetch();
        return(vl);
}
 
/*
 * unary : factor | unop unary
 *
 */
unary()
{
        register int val, c;
 
        if ((c = skipws()) == '!' || c == '~' || c == '-') {
                val = unary();
 
                switch (c) {
                case '!':
                        return(! val);
                case '~':
                        return(~ val);
                case '-':
                        return(- val);
                }
        }
 
        ungetch();
        return(factor());
}
 
/*
 * factor : constant | '(' query ')'
 *
 */
factor()
{
        register int val;
 
        if (skipws() == '(') {
                val = query();
                if (skipws() != ')')
                        experr("Bad factor");
                return(val);
        }
 
        ungetch();
        return(constant());
}
 
/*
 * constant: num | 'char'
 *
 */
constant()
{
        /*
         * Note: constant() handles multi-byte constants
         */
 
        register int    i;
        register int    value;
        register char   c;
        int             v[sizeof (int)];
 
        if (skipws() != '\'') {
                ungetch();
                return(num());
        }
        for (i = 0; i < sizeof(int); i++) {
                if ((c = getch()) == '\'') {
                        ungetch();
                        break;
                }
                if (c == '\\') {
                        switch (c = getch()) {
                        case '0':
                        case '1':
                        case '2':
                        case '3':
                        case '4':
                        case '5':
                        case '6':
                        case '7':
                                ungetch();
                                c = num();
                                break;
                        case 'n':
                                c = 012;
                                break;
                        case 'r':
                                c = 015;
                                break;
                        case 't':
                                c = 011;
                                break;
                        case 'b':
                                c = 010;
                                break;
                        case 'f':
                                c = 014;
                                break;
                        }
                }
                v[i] = c;
        }
        if (i == 0 || getch() != '\'')
                experr("Illegal character constant");
        for (value = 0; --i >= 0;) {
                value <<= 8;
                value += v[i];
        }
        return(value);
}
 
/*
 * num : digit | num digit
 *
 */
num()
{
        register int rval, c, base;
        int ndig;
 
        base = ((c = skipws()) == '0') ? OCTAL : DECIMAL;
        rval = 0;
        ndig = 0;
        while (c >= '0' && c <= (base == OCTAL ? '7' : '9')) {
                rval *= base;
                rval += (c - '0');
                c = getch();
                ndig++;
        }
        ungetch();
        if (ndig)
                return(rval);
        experr("Bad constant");
}
 
/*
 * eqlrel : '=' | '==' | '!='
 *
 */
geteql()
{
        register int c1, c2;
 
        c1 = skipws();
        c2 = getch();
 
        switch (c1) {
 
        case '=':
                if (c2 != '=')
                        ungetch();
                return(EQL);
 
        case '!':
                if (c2 == '=')
                        return(NEQ);
                ungetch();
                ungetch();
                return(-1);
 
        default:
                ungetch();
                ungetch();
                return(-1);
        }
}
 
/*
 * rel : '<' | '>' | '<=' | '>='
 *
 */
getrel()
{
        register int c1, c2;
 
        c1 = skipws();
        c2 = getch();
 
        switch (c1) {
 
        case '<':
                if (c2 == '=')
                        return(LEQ);
                ungetch();
                return(LSS);
 
        case '>':
                if (c2 == '=')
                        return(GEQ);
                ungetch();
                return(GTR);
 
        default:
                ungetch();
                ungetch();
                return(-1);
        }
}
 
/*
 * Skip over any white space and return terminating char.
 */
skipws()
{
        register char c;
 
        while ((c = getch()) <= ' ' && c > EOS)
                ;
        return(c);
}
 
/*
 * Error handler - resets environment to eval(), prints an error,
 * and returns FALSE.
 */
experr(msg)
char *msg;
{
        printf("mp: %s\n",msg);
        longjmp(expjump, -1);          /* Force eval() to return FALSE */
}
@


1.1.1.1
log
@initial import of 386bsd-0.1 sources
@
text
@@


1.1.1.2
log
@imported from 44lite2
@
text
@d2 2
a3 2
 * Copyright (c) 1989, 1993
 *	The Regents of the University of California.  All rights reserved.
d6 1
a6 1
 * Ozan Yigit at York University.
d38 1
a38 1
static char sccsid[] = "@@(#)expr.c	8.2 (Berkeley) 4/29/95";
d41 1
a41 1
#include <sys/cdefs.h>
d53 6
a58 4
 *      land    :       not { "&&" not }
 *	not	:	eqrel
 *		|	'!' not
 *      eqrel   :       shift { eqrelop shift }
d61 1
a61 2
 *      term    :       exp { mulop exp }
 *	exp	:	unary { expop unary }
d72 1
a72 1
 *      eqrel   :       "="
d75 1
a75 1
 *      	|       "<"
d88 1
a88 1

d100 3
a102 20

static char *nxtch;		       /* Parser scan pointer */

static int query __P((void));
static int lor __P((void));
static int land __P((void));
static int not __P((void));
static int eqrel __P((void));
static int shift __P((void));
static int primary __P((void));
static int term __P((void));
static int exp __P((void));
static int unary __P((void));
static int factor __P((void));
static int constant __P((void));
static int num __P((void));
static int geteqrel __P((void));
static int skipws __P((void));
static void experr __P((char *));

d106 2
a107 3
#include <setjmp.h>
static jmp_buf expjump;

d110 1
d116 1
a116 2

int
d120 9
a128 12
	register int rval;

	nxtch = expbuf;
	if (setjmp(expjump) != 0)
		return FALSE;

	rval = query();
	if (skipws() == EOS)
		return rval;

	printf("m4: ill-formed expression.\n");
	return FALSE;
d130 1
a130 1

d133 1
a134 1
static int
d137 14
a150 14
	register int bool, true_val, false_val;

	bool = lor();
	if (skipws() != '?') {
		ungetch();
		return bool;
	}

	true_val = query();
	if (skipws() != ':')
		experr("bad query");

	false_val = query();
	return bool ? true_val : false_val;
d152 1
a152 1

d155 1
a156 1
static int
d159 12
a170 12
	register int c, vl, vr;

	vl = land();
	while ((c = skipws()) == '|') {
		if (getch() != '|')
			ungetch();
		vr = land();
		vl = vl || vr;
	}

	ungetch();
	return vl;
d172 1
a172 1

d174 2
a175 1
 * land : not { '&&' not }
a176 1
static int
d179 72
a250 12
	register int c, vl, vr;

	vl = not();
	while ((c = skipws()) == '&') {
		if (getch() != '&')
			ungetch();
		vr = not();
		vl = vl && vr;
	}

	ungetch();
	return vl;
d252 1
a252 1

d254 2
a255 1
 * not : eqrel | '!' not
d257 1
a257 2
static int
not()
d259 17
a275 12
	register int val, c;

	if ((c = skipws()) == '!' && getch() != '=') {
		ungetch();
		val = not();
		return !val;
	}

	if (c == '!')
		ungetch();
	ungetch();
	return eqrel();
d277 1
a277 1

d279 2
a280 1
 * eqrel : shift { eqrelop shift }
d282 1
a282 2
static int
eqrel()
d284 23
a306 30
	register int vl, vr, eqrel;

	vl = shift();
	while ((eqrel = geteqrel()) != -1) {
		vr = shift();

		switch (eqrel) {

		case EQL:
			vl = (vl == vr);
			break;
		case NEQ:
			vl = (vl != vr);
			break;

		case LEQ:
			vl = (vl <= vr);
			break;
		case LSS:
			vl = (vl < vr);
			break;
		case GTR:
			vl = (vl > vr);
			break;
		case GEQ:
			vl = (vl >= vr);
			break;
		}
	}
	return vl;
d308 1
a308 1

d311 1
a312 1
static int
d315 16
a330 16
	register int vl, vr, c;

	vl = primary();
	while (((c = skipws()) == '<' || c == '>') && getch() == c) {
		vr = primary();

		if (c == '<')
			vl <<= vr;
		else
			vl >>= vr;
	}

	if (c == '<' || c == '>')
		ungetch();
	ungetch();
	return vl;
d332 1
a332 1

d335 1
a336 1
static int
d339 13
a351 14
	register int c, vl, vr;

	vl = term();
	while ((c = skipws()) == '+' || c == '-') {
		vr = term();

		if (c == '+')
			vl += vr;
		else
			vl -= vr;
	}

	ungetch();
	return vl;
d353 1
a353 1

d355 2
a356 1
 * <term> := <exp> { <mulop> <exp> }
a357 1
static int
d360 20
a379 20
	register int c, vl, vr;

	vl = exp();
	while ((c = skipws()) == '*' || c == '/' || c == '%') {
		vr = exp();

		switch (c) {
		case '*':
			vl *= vr;
			break;
		case '/':
			vl /= vr;
			break;
		case '%':
			vl %= vr;
			break;
		}
	}
	ungetch();
	return vl;
d381 1
a381 30

/*
 * <term> := <unary> { <expop> <unary> }
 */
static int
exp()
{
	register c, vl, vr, n;

	vl = unary();
	switch (c = skipws()) {

	case '*':
		if (getch() != '*') {
			ungetch();
			break;
		}

	case '^':
		vr = exp();
		n = 1;
		while (vr-- > 0)
			n *= vl;
		return n;
	}

	ungetch();
	return vl;
}

d384 1
a385 1
static int
d388 17
a404 17
	register int val, c;

	if ((c = skipws()) == '+' || c == '-' || c == '~') {
		val = unary();

		switch (c) {
		case '+':
			return val;
		case '-':
			return -val;
		case '~':
			return ~val;
		}
	}

	ungetch();
	return factor();
d406 1
a406 1

d409 1
a410 1
static int
d413 11
a423 11
	register int val;

	if (skipws() == '(') {
		val = query();
		if (skipws() != ')')
			experr("bad factor");
		return val;
	}

	ungetch();
	return constant();
d425 1
a425 1

d428 1
a428 1
 * Note: constant() handles multi-byte constants
a429 1
static int
d432 57
a488 53
	register int i;
	register int value;
	register char c;
	int v[sizeof(int)];

	if (skipws() != '\'') {
		ungetch();
		return num();
	}
	for (i = 0; i < sizeof(int); i++) {
		if ((c = getch()) == '\'') {
			ungetch();
			break;
		}
		if (c == '\\') {
			switch (c = getch()) {
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
				ungetch();
				c = num();
				break;
			case 'n':
				c = 012;
				break;
			case 'r':
				c = 015;
				break;
			case 't':
				c = 011;
				break;
			case 'b':
				c = 010;
				break;
			case 'f':
				c = 014;
				break;
			}
		}
		v[i] = c;
	}
	if (i == 0 || getch() != '\'')
		experr("illegal character constant");
	for (value = 0; --i >= 0;) {
		value <<= 8;
		value += v[i];
	}
	return value;
d490 1
a490 1

d493 1
a494 1
static int
d497 48
a544 19
	register int rval, c, base;
	int ndig;

	base = ((c = skipws()) == '0') ? OCTAL : DECIMAL;
	rval = 0;
	ndig = 0;
	while (c >= '0' && c <= (base == OCTAL ? '7' : '9')) {
		rval *= base;
		rval += (c - '0');
		c = getch();
		ndig++;
	}
	ungetch();
	
	if (ndig == 0)
		experr("bad constant");
	
	return rval;

d546 1
a546 1

d548 2
a549 1
 * eqrel : '=' | '==' | '!=' | '<' | '>' | '<=' | '>='
d551 1
a551 2
static int
geteqrel()
d553 24
a576 36
	register int c1, c2;

	c1 = skipws();
	c2 = getch();

	switch (c1) {

	case '=':
		if (c2 != '=')
			ungetch();
		return EQL;

	case '!':
		if (c2 == '=')
			return NEQ;
		ungetch();
		ungetch();
		return -1;

	case '<':
		if (c2 == '=')
			return LEQ;
		ungetch();
		return LSS;

	case '>':
		if (c2 == '=')
			return GEQ;
		ungetch();
		return GTR;

	default:
		ungetch();
		ungetch();
		return -1;
	}
d578 1
a578 1

a581 1
static int
d584 5
a588 5
	register char c;

	while ((c = getch()) <= ' ' && c > EOS)
		;
	return c;
d590 1
a590 1

d592 2
a593 2
 * resets environment to eval(), prints an error 
 * and forces eval to return FALSE.
a594 1
static void
d598 2
a599 2
	printf("m4: %s in expr.\n", msg);
	longjmp(expjump, -1);
@


1.1.1.3
log
@Import new m4 from OpenBSD.
@
text
@a0 1
/* $OpenBSD: expr.c,v 1.17 2006/01/20 23:10:19 espie Exp $ */
d2 2
a3 1
 * Copyright (c) 2004 Marc Espie <espie@@cvs.openbsd.org>
d5 30
a34 11
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
d36 6
a41 1
#include <stdint.h>
a42 3
#include <stddef.h>
#include "mdef.h"
#include "extern.h"
d44 57
a100 2
int32_t end_result;
const char *copy_toeval;
d102 30
a131 2
extern void yy_scan_string(const char *);
extern int yyparse(void);
d134 84
a217 1
yyerror(const char *msg)
d219 12
a230 2
	fprintf(stderr, "m4: %s in expr %s\n", msg, copy_toeval);
	return(0);
d233 338
a570 2
int 
expr(const char *toeval)
d572 2
a573 4
	copy_toeval = toeval;
	yy_scan_string(toeval);
	yyparse();
	return end_result;
@

