| --- vbcc-0.7.orig/debian/dirs | |
| +++ vbcc-0.7/debian/dirs | |
| @@ -0,0 +1 @@ | |
| +usr/bin | |
| --- vbcc-0.7.orig/debian/vbcc.files | |
| +++ vbcc-0.7/debian/vbcc.files | |
| +/usr/bin | |
| +/usr/lib/vbcc | |
| +/usr/share/vbcc | |
| +/usr/share/man | |
| --- vbcc-0.7.orig/debian/README.Debian | |
| +++ vbcc-0.7/debian/README.Debian | |
| +vbcc for Debian | |
| +--------------- | |
| + | |
| +This is a Debianisation of Volker Barthelmann's vbcc compiler. The original | |
| +upstream distribution site is: | |
| + | |
| + http://www.compilers.de/vbcc/ | |
| + | |
| +Note that this is version 0.7; the latest upstream version is 0.8. | |
| + | |
| + -- David Given <dg@cowlark.com>, Fri, 2 Nov 2001 20:59:17 +0000 | |
| --- vbcc-0.7.orig/debian/rules | |
| +++ vbcc-0.7/debian/rules | |
| +#!/usr/bin/make -f | |
| +# Sample debian/rules that uses debhelper. | |
| +# GNU copyright 1997 to 1999 by Joey Hess. | |
| + | |
| +# Uncomment this to turn on verbose mode. | |
| +#export DH_VERBOSE=1 | |
| + | |
| +# This is the debhelper compatability version to use. | |
| +export DH_COMPAT=3 | |
| + | |
| +configure: configure-stamp | |
| +configure-stamp: | |
| + dh_testdir | |
| + | |
| + autoconf | |
| + ./configure --prefix=/usr --mandir=\$${prefix}/share/man --infodir=\$${prefix}/share/info | |
| + | |
| + touch configure-stamp | |
| + | |
| +build: configure-stamp build-stamp | |
| +build-stamp: | |
| + dh_testdir | |
| + | |
| + mkdir -p bin | |
| + $(MAKE) | |
| + | |
| + touch build-stamp | |
| + | |
| +clean: configure | |
| + dh_testdir | |
| + dh_testroot | |
| + | |
| + if [ -f Makefile ]; then $(MAKE) clean; fi | |
| + rm -f Makefile config.cache config.log config.status | |
| + rm -f build-stamp configure-stamp | |
| + | |
| + dh_clean | |
| + | |
| +install: build | |
| + dh_testdir | |
| + dh_testroot | |
| + dh_clean -k | |
| + dh_installdirs | |
| + | |
| + mkdir -p debian/tmp/usr/bin | |
| + mkdir -p debian/tmp/usr/lib/vbcc | |
| + cp bin/* debian/tmp/usr/lib/vbcc | |
| + mv debian/tmp/usr/lib/vbcc/vc debian/tmp/usr/bin | |
| + | |
| + mkdir -p debian/tmp/usr/share/man/man1 | |
| + cp vc.1 debian/tmp/usr/share/man/man1 | |
| + | |
| + cp -r share debian/tmp/usr | |
| + | |
| + | |
| +# Build architecture-independent files here. | |
| +binary-indep: build install | |
| +# We have nothing to do by default. | |
| + | |
| +# Build architecture-dependent files here. | |
| +binary-arch: build install | |
| + dh_testdir | |
| + dh_testroot | |
| + dh_movefiles | |
| + | |
| +# dh_installdebconf | |
| + dh_installdocs | |
| + dh_installexamples | |
| + dh_installmenu | |
| +# dh_installlogrotate | |
| +# dh_installemacsen | |
| +# dh_installpam | |
| +# dh_installmime | |
| +# dh_installinit | |
| + dh_installcron | |
| + dh_installman | |
| + dh_installinfo | |
| +# dh_undocumented | |
| + dh_installchangelogs | |
| + dh_link | |
| + dh_strip | |
| + dh_compress | |
| + dh_fixperms | |
| +# dh_makeshlibs | |
| + dh_installdeb | |
| +# dh_perl | |
| + dh_shlibdeps | |
| + dh_gencontrol | |
| + dh_md5sums | |
| + dh_builddeb | |
| + | |
| +binary: binary-indep binary-arch | |
| +.PHONY: build clean binary-indep binary-arch binary install configure | |
| --- vbcc-0.7.orig/debian/vbcc.docs | |
| +++ vbcc-0.7/debian/vbcc.docs | |
| @@ -0,0 +1 @@ | |
| +doc | |
| --- vbcc-0.7.orig/debian/copyright | |
| +++ vbcc-0.7/debian/copyright | |
| +This package was debianized by David Given <dg@hilfy> on | |
| +Fri, 2 Nov 2001 20:59:17 +0000. | |
| + | |
| +It was downloaded from http://www.compilers.de | |
| + | |
| +Upstream Author(s): Volker Barthelmann | |
| + | |
| +Copyright: | |
| + | |
| +vbcc compiler | |
| + | |
| + vbcc is (c) in 1995-99 by Volker Barthelmann. The builtin preprocessor | |
| + (consisting of the files preproc.c and vbpp.h) is written and (c) by | |
| + Thorsten Schaaps. All other code is (c) by Volker Barthelmann. | |
| + vbcc may be freely redistributed as long as no modifications are made | |
| + and nothing is charged for it. | |
| + Non-commercial usage of vbcc is allowed without any restrictions. | |
| + Commercial usage needs my written consent. | |
| + | |
| + Sending me money, gifts, postcards etc. would be very nice and may | |
| + encourage further development of vbcc, but is not legally or morally | |
| + necessary to use vbcc. | |
| + | |
| +vcpp preprocessor | |
| + | |
| + The authors of this software are Christopher W. Fraser and | |
| + David R. Hanson. | |
| + | |
| + Copyright (c) 1991,1992,1993,1994,1995 by AT&T, Christopher W. Fraser, | |
| + and David R. Hanson. All Rights Reserved. | |
| + | |
| + Permission to use, copy, modify, and distribute this software for any | |
| + purpose, subject to the provisions described below, without fee is | |
| + hereby granted, provided that this entire notice is included in all | |
| + copies of any software that is or includes a copy or modification of | |
| + this software and in all copies of the supporting documentation for | |
| + such software. | |
| + | |
| + THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED | |
| + WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR AT&T MAKE ANY | |
| + REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY | |
| + OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. | |
| + | |
| + | |
| + lcc is not public-domain software, shareware, and it is not protected | |
| + by a `copyleft' agreement, like the code from the Free Software | |
| + Foundation. | |
| + | |
| + lcc is available free for your personal research and instructional use | |
| + under the `fair use' provisions of the copyright law. You may, | |
| + however, redistribute the lcc in whole or in part provided you | |
| + acknowledge its source and include this COPYRIGHT file. | |
| + | |
| + You may not sell lcc or any product derived from it in which it is a | |
| + significant part of the value of the product. Using the lcc front end | |
| + to build a C syntax checker is an example of this kind of product. | |
| + | |
| + You may use parts of lcc in products as long as you charge for only | |
| + those components that are entirely your own and you acknowledge the use | |
| + of lcc clearly in all product documentation and distribution media. You | |
| + must state clearly that your product uses or is based on parts of lcc | |
| + and that lcc is available free of charge. You must also request that | |
| + bug reports on your product be reported to you. Using the lcc front | |
| + end to build a C compiler for the Motorola 88000 chip and charging for | |
| + and distributing only the 88000 code generator is an example of this | |
| + kind of product. | |
| + | |
| + Using parts of lcc in other products is more problematic. For example, | |
| + using parts of lcc in a C++ compiler could save substantial time and | |
| + effort and therefore contribute significantly to the profitability of | |
| + the product. This kind of use, or any use where others stand to make a | |
| + profit from what is primarily our work, is subject to negotiation. | |
| + | |
| +Debianisation code and Z-machine code generator | |
| + | |
| + This code is licensed under the MIT open source license. | |
| + | |
| + Copyright (c) 2001, David Given | |
| + All rights reserved. | |
| + | |
| + Permission is hereby granted, free of charge, to any person obtaining a | |
| + copy of this software and associated documentation files (the "Software"), | |
| + to deal in the Software without restriction, including without limitation | |
| + the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| + and/or sell copies of the Software, and to permit persons to whom the | |
| + Software is furnished to do so, subject to the following conditions: | |
| + | |
| + The above copyright notice and this permission notice shall be included in | |
| + all copies or substantial portions of the Software. | |
| + | |
| + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
| + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
| + DEALINGS IN THE SOFTWARE. | |
| + | |
| --- vbcc-0.7.orig/debian/changelog | |
| +++ vbcc-0.7/debian/changelog | |
| +vbcc (0.7-3) unstable; urgency=high | |
| + | |
| + * Moved vc.1 from /usr/man to /usr/share/man to comply with the filesystem | |
| + standard. So *that's* why half my man pages are in /usr/share... | |
| + | |
| + -- David Given <dg@cowlark.com> Mon, 14 Jan 2002 12:11:39 +0000 | |
| + | |
| +vbcc (0.7-2) unstable; urgency=high | |
| + | |
| + * Danger, Will Robinson! Uninitialised variable! Fails horribly on OS X! | |
| + | |
| + -- David Given <dg@cowlark.com> Sat, 17 Nov 2001 23:39:17 +0000 | |
| + | |
| +vbcc (0.7-1) unstable; urgency=low | |
| + | |
| + * Initial Release. | |
| + | |
| + -- David Given <dg@cowlark.com> Fri, 2 Nov 2001 20:59:17 +0000 | |
| + | |
| +Local variables: | |
| +mode: debian-changelog | |
| +End: | |
| --- vbcc-0.7.orig/debian/control | |
| +++ vbcc-0.7/debian/control | |
| +Source: vbcc | |
| +Section: devel | |
| +Priority: optional | |
| +Maintainer: David Given <dg@cowlark.com> | |
| +Build-Depends: debhelper (>> 3.0.0) | |
| +Standards-Version: 3.5.2 | |
| + | |
| +Package: vbcc | |
| +Architecture: any | |
| +Depends: ${shlibs:Depends} | |
| +Description: Lightweight retargetable optimising C compiler | |
| + vbcc is a free portable and retargetable ANSI C compiler which can generate | |
| + code for a wide variety of processors. It can perform any of a large range | |
| + of optimisations on the emitted code; in some areas it can produce better | |
| + code than gcc. | |
| + . | |
| + This version contains code generators for: alpha, c16x, i386, m68k, PowerPC, | |
| + and Infocom's Z-machine. | |
| --- vbcc-0.7.orig/vc.1 | |
| +++ vbcc-0.7/vc.1 | |
| +.TH vc 1 "11 Nov 2001" | |
| +.SH NAME | |
| +vc \- front end to the vbcc compiler suite | |
| + | |
| +.SH SYNOPSIS | |
| +.B vc | |
| +.BI + "target" | |
| +[ | |
| +.I options | |
| +] | |
| +[ | |
| +.I input-files | |
| +] | |
| + | |
| +.SH DESCRIPTION | |
| +.B vc | |
| +is the front-end to the vbcc compiler suite. It should be reasonably compatible | |
| +with the standard Unix | |
| +.B cc | |
| +program, with a few minor changes. | |
| +.P | |
| +vbcc is a cross-platform compiler. As a result it is necessary to tell the | |
| +compiler which target to generate code for. This is done with the required | |
| +.BI + "target" | |
| +option. The following targets are supported: | |
| +.TP | |
| +.BR i386 | |
| +Intel 386 series. | |
| +.TP | |
| +.BR ppc | |
| +Any Motorola PowerPC series processor. | |
| +.TP | |
| +.BR m68k | |
| +Any Motorola 68000 series processor. | |
| +.TP | |
| +.BR alpha | |
| +DEC's Alpha series. | |
| +.TP | |
| +.BR c16x | |
| +The SAB C16X microprocessor. | |
| +.TP | |
| +.BR z | |
| +Infocom's Z-machine. | |
| +.P | |
| +vbcc does not provide a complete toolchain, only the compiler. As a result, you | |
| +will need the appropriate assembler and linker to use the code produced by | |
| +vbcc. Unfortunately, vbcc cannot know which toolchain you are using, and as a | |
| +result | |
| +.B vc | |
| +does not know how to assemble and link files. | |
| +.P | |
| +For more information on the code generators, descriptions of the | |
| +platform-specific flags available, how to create configuration files, and | |
| +detailed information on the more arcane options that | |
| +.B vc | |
| +supports, see | |
| +.BR /usr/share/doc/vbcc/doc . | |
| + | |
| +.SH OPTIONS | |
| +(Commonly used options only) | |
| + | |
| +.TP | |
| +.BR -v | |
| +verbose; print all commands | |
| +.TP | |
| +.BR -vv | |
| +very verbose; display some internals as well | |
| +.TP | |
| +.BR -Ox | |
| +optimisation level | |
| +.TP | |
| +.BI -o file | |
| +save target as | |
| +.I file | |
| +(default for executables is a.out) | |
| +.TP | |
| +.BR -E | |
| +do not compile, save the preprocessed C sources | |
| +.TP | |
| +.BR -S | |
| +do not assemble, save the compiled files | |
| +.TP | |
| +.BR -SCS | |
| +do not schedule, save the compiled files | |
| +.TP | |
| +.BR -c | |
| +do not link, save the assembled files | |
| +.TP | |
| +.BR -k | |
| +keep all intermediate files; by default all temporary files are removed | |
| +.TP | |
| +.BI -D string | |
| +define a preprocessor symbol, e.g. | |
| +.I -DAMIGA | |
| +or | |
| +.I -DCPU=68000 | |
| +.TP | |
| +.BI -I path | |
| +add the path to the include file search path | |
| +.TP | |
| +.BI -l lib | |
| +link with the library | |
| +.I lib | |
| +.TP | |
| +.B -nostdlib | |
| +do not link with the standard libraries; useful only for experts | |
| +.TP | |
| +.B -notmpfile | |
| +do not use names from tmpnam() for temporary files | |
| +.TP | |
| +.B -schedule | |
| +do instruction scheduling (not supported in the Debian version) | |
| +.P | |
| +All other options are passed through to the compiler. | |
| + | |
| +.SH SEE ALSO | |
| +The main vbcc documentation is in | |
| +.IR /usr/share/doc/vbcc/doc . | |
| + | |
| +.SH AUTHORS | |
| +Main compiler (C) 1995-1999 Volker Barthelmann; see | |
| +.I vbcc.doc | |
| +for license | |
| +.P | |
| +Preprocessor taken from the lcc distribution, with minor alterations. | |
| +(C) 1991-1995 AT&T, Chris Fraser and David Hanson. See | |
| +.I vcpp.doc | |
| +for license and full details | |
| +.P | |
| +Z-machine code generator (C) 2001 David Given under the MIT license; see | |
| +.I vbccz.doc | |
| +for full license | |
| +.P | |
| +Additional code in the Debian version by David Given is in the public domain | |
| + | |
| --- vbcc-0.7.orig/machines/z/machine.dt | |
| +++ vbcc-0.7/machines/z/machine.dt | |
| +S8BS | |
| +S8BU | |
| +S16BSLE S16BSBE | |
| +S16BULE S16BUBE | |
| +S16BSLE S16BSBE | |
| +S16BULE S16BUBE | |
| +S32BSLE S32BSBE | |
| +S32BULE S32BUBE | |
| +S32BIEEEBE S32BIEEELE | |
| +S64BIEEEBE S64BIEEELE | |
| +S16BULE S16BUBE | |
| --- vbcc-0.7.orig/machines/z/machine.h | |
| +++ vbcc-0.7/machines/z/machine.h | |
| +/* Z-machine code generator | |
| + * David Given | |
| + */ | |
| + | |
| +#include "dt.h" | |
| + | |
| +/* Machine specific addressing-modes. Not used. */ | |
| + | |
| +struct AddressingMode{ | |
| + int never_used; | |
| +}; | |
| + | |
| +/* The number of registers we support. We don't really have any, but we | |
| + * use local variables instead; we have 14. | |
| + */ | |
| + | |
| +#define MAXR 14 | |
| + | |
| +/* Number of command-line options we accept. */ | |
| + | |
| +#define MAXGF 6 | |
| + | |
| +/* If this is set to zero vbcc will not generate ICs where the target operand | |
| + * is the same as the 2nd source operand. This can sometimes simplify the | |
| + * code-generator, but usually the code is better if the code-generator allows | |
| + * it. | |
| + */ | |
| + | |
| +#define USEQ2ASZ 1 | |
| + | |
| +/* The smallest and largest integer type that can be added to a pointer. */ | |
| + | |
| +#define MINADDI2P INT | |
| +#define MAXADDI2P INT | |
| + | |
| +/* Big-endian? */ | |
| + | |
| +#define BIGENDIAN 1 | |
| + | |
| +/* Little-endian? */ | |
| + | |
| +#define LITTLEENDIAN 0 | |
| + | |
| +/* If switch-statements should be generated as a sequence of SUB,TST,BEQ ICs | |
| + * rather than COMPARE,BEQ ICs set this to 1. This can yield better code on | |
| + * some machines. | |
| + */ | |
| + | |
| +#define SWITCHSUBS 0 | |
| + | |
| +/* In optimizing compilation certain library memcpy/strcpy-calls with length | |
| + * known at compile-time will be inlined using an ASSIGN-IC if the size is less | |
| + * or equal to INLINEMEMCPY. The type used for the ASSIGN-IC will be | |
| + * UNSIGNED|CHAR. On the Z-machine, memcpy can be done in `hardware' with the | |
| + * @copy_table opcode, so always inline them if possible. | |
| + */ | |
| + | |
| +#define INLINEMEMCPY 65536 | |
| + | |
| +/* Do we want to pass parameters to functions in registers? */ | |
| + | |
| +#define HAVE_REGPARMS | |
| + | |
| +/* If so, how many? Max 7 due to the architecture, but one is always xp. */ | |
| + | |
| +#define NUM_REGPARMS 6 | |
| + | |
| +/* This structure is used to keep track of where register parameters go. */ | |
| + | |
| +struct reg_handle { | |
| + int reg; | |
| +}; | |
| + | |
| +/* Do we want to use zuint for size_t rather than the default zulong? */ | |
| + | |
| +#define HAVE_INT_SIZET 1 | |
| + | |
| --- vbcc-0.7.orig/machines/z/machine.c | |
| +++ vbcc-0.7/machines/z/machine.c | |
| +/* z/machine.c | |
| + * Code generator for the Z-machine. | |
| + * (C) David Given 2001 | |
| + */ | |
| + | |
| +/* This code is licensed under the MIT open source license. | |
| + * | |
| + * Copyright (c) 2001, David Given | |
| + * All rights reserved. | |
| + * | |
| + * Permission is hereby granted, free of charge, to any person obtaining a | |
| + * copy of this software and associated documentation files (the "Software"), | |
| + * to deal in the Software without restriction, including without limitation | |
| + * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| + * and/or sell copies of the Software, and to permit persons to whom the | |
| + * Software is furnished to do so, subject to the following conditions: | |
| + * | |
| + * The above copyright notice and this permission notice shall be included in | |
| + * all copies or substantial portions of the Software. | |
| + * | |
| + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
| + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
| + * DEALINGS IN THE SOFTWARE. | |
| + */ | |
| + | |
| +/* This code generator produces code for the Z-machine. The Z-machine is the | |
| + * highly peculiar virtual machine used for the old Infocom text adventures; | |
| + * these days, an extended form is still used in the interactive fiction genre | |
| + * of games. Usually, a dedicated compiler called Inform is used to generate | |
| + * code, but it would be nice to be able to use real C, so here we are. | |
| + * | |
| + * The Z-machine is (mostly) a semi-stack-based Harvard architecture machine. | |
| + * (Split code and data space, although they can share if you're clever. And | |
| + * mad.) It has no registers, but it does have procedure local variables which | |
| + * will do instead. It has a dedicated stack but as it's not accessible by | |
| + * ordinary memory it's not useful for C. It uses 8 and 16 bit words, so we'll | |
| + * have to emulate 32-bit arithmetic. | |
| + * | |
| + * For more information, including code for Inform, various interpreters, more | |
| + * documentation than you can shake a stick at, and the full technical reference | |
| + * for the Z-machine, check out the Interactive Fiction archive, at | |
| + * http://www.ifarchive.org. | |
| + * | |
| + * Things to note: there is no Z-machine assembler. (Well, there's zasm, but it's | |
| + * really just a rumour.) Luckily, Inform has an assembler mode, where it'll | |
| + * generate raw Z-machine opcodes. Unluckily, it's horribly buggy... So we're | |
| + * going to have to generate Inform source, which seems at first to be rather | |
| + * silly, but as Inform is quite a simple compiler we can make sure that it's | |
| + * only going to generate the instructions we want it to generate. | |
| + */ | |
| + | |
| +/* vbcc-mandated header. */ | |
| + | |
| +#include "supp.h" | |
| +static char FILE_[]=__FILE__; | |
| +char cg_copyright[]="vbcc code-generator for Z-machine V0.0 (c) in 2001 by David Given"; | |
| + | |
| +/* Command-line flags. */ | |
| + | |
| +int g_flags[MAXGF] = { | |
| + STRINGFLAG, | |
| + 0, | |
| + 0, | |
| + 0, | |
| + 0, | |
| + 0 | |
| +}; | |
| +char *g_flags_name[MAXGF] = { | |
| + "module-name", | |
| + "trace-calls", | |
| + "trace-all", | |
| + "safe-branches", | |
| + "comment-ic", | |
| + "comment-misc" | |
| +}; | |
| +union ppi g_flags_val[MAXGF]; | |
| + | |
| +/* Type alignment. Much better code is generated if we can use even alignment. | |
| + */ | |
| + | |
| +zlong align[16] = { | |
| + 0, /* 0: unused */ | |
| + 1, /* 1: CHAR */ | |
| + 2, /* 2: SHORT */ | |
| + 2, /* 3: INT */ | |
| + 2, /* 4: LONG */ | |
| + 2, /* 5: FLOAT */ | |
| + 2, /* 6: DOUBLE */ | |
| + 2, /* 7: VOID */ | |
| + 2, /* 8: POINTER */ | |
| + 1, /* 9: ARRAY */ | |
| + 1, /* 10: STRUCT */ | |
| + 1, /* 11: UNION */ | |
| + 1, /* 12: ENUM */ | |
| + 1, /* 13: FUNKT */ | |
| + 0, /* 14: unused */ | |
| + 0, /* 15: unused */ | |
| +}; | |
| + | |
| +/* Alignment that is valid for all types. */ | |
| + | |
| +zlong maxalign = 2; | |
| + | |
| +/* Number of bits in a char. */ | |
| + | |
| +zlong char_bit = 8; | |
| + | |
| +/* Sizes of all elementary types, in bytes. */ | |
| + | |
| +zlong sizetab[16] = { | |
| + 0, /* 0: unused */ | |
| + 1, /* 1: CHAR */ | |
| + 2, /* 2: SHORT */ | |
| + 2, /* 3: INT */ | |
| + 4, /* 4: LONG */ | |
| + 4, /* 5: FLOAT */ | |
| + 8, /* 6: DOUBLE */ | |
| + 0, /* 7: VOID */ | |
| + 2, /* 8: POINTER */ | |
| + 0, /* 9: ARRAY */ | |
| + 0, /* 10: STRUCT */ | |
| + 0, /* 11: UNION */ | |
| + 2, /* 12: ENUM */ | |
| + 0, /* 13: FUNKT */ | |
| + 0, /* 14: unused */ | |
| + 0, /* 15: unused */ | |
| +}; | |
| + | |
| +/* Minimum and Maximum values each type can have. | |
| + */ | |
| + | |
| +zlong t_min[32] = { | |
| + /* Signed: */ | |
| + 0, /* 0: unused */ | |
| + -128L, /* 1: CHAR */ | |
| + -32768L, /* 2: SHORT */ | |
| + -32768L, /* 3: INT */ | |
| + -2147483647L, /* 4: LONG */ | |
| + 0, /* 5: FLOAT */ | |
| + 0, /* 6: DOUBLE */ | |
| + 0, /* 7: VOID */ | |
| + 0, /* 8: POINTER */ | |
| + 0, /* 9: ARRAY */ | |
| + 0, /* 10: STRUCT */ | |
| + 0, /* 11: UNION */ | |
| + 0, /* 12: ENUM */ | |
| + 0, /* 13: FUNKT */ | |
| + 0, /* 14: unused */ | |
| + 0, /* 15: unused */ | |
| + 0, /* 0: unused */ | |
| + /* Unsigned: */ | |
| + 0, /* 1: CHAR */ | |
| + 0, /* 2: SHORT */ | |
| + 0, /* 3: INT */ | |
| + 0, /* 4: LONG */ | |
| + 0, /* 5: FLOAT */ | |
| + 0, /* 6: DOUBLE */ | |
| + 0, /* 7: VOID */ | |
| + 0, /* 8: POINTER */ | |
| + 0, /* 9: ARRAY */ | |
| + 0, /* 10: STRUCT */ | |
| + 0, /* 11: UNION */ | |
| + 0, /* 12: ENUM */ | |
| + 0, /* 13: FUNKT */ | |
| + 0, /* 14: unused */ | |
| + 0, /* 15: unused */ | |
| +}; | |
| +zulong t_max[32] = { | |
| + /* Signed: */ | |
| + 0, /* 0: unused */ | |
| + 127UL, /* 1: CHAR */ | |
| + 32767UL, /* 2: SHORT */ | |
| + 32767UL, /* 3: INT */ | |
| + 2147483647UL, /* 4: LONG */ | |
| + 0, /* 5: FLOAT */ | |
| + 0, /* 6: DOUBLE */ | |
| + 0, /* 7: VOID */ | |
| + 0, /* 8: POINTER */ | |
| + 0, /* 9: ARRAY */ | |
| + 0, /* 10: STRUCT */ | |
| + 0, /* 11: UNION */ | |
| + 0, /* 12: ENUM */ | |
| + 0, /* 13: FUNKT */ | |
| + 0, /* 14: unused */ | |
| + 0, /* 15: unused */ | |
| + 0, /* 0: unused */ | |
| + /* Unsigned: */ | |
| + 255UL, /* 1: CHAR */ | |
| + 65535UL, /* 2: SHORT */ | |
| + 65535UL, /* 3: INT */ | |
| + 4294967295UL, /* 4: LONG */ | |
| + 0, /* 5: FLOAT */ | |
| + 0, /* 6: DOUBLE */ | |
| + 0, /* 7: VOID */ | |
| + 0, /* 8: POINTER */ | |
| + 0, /* 9: ARRAY */ | |
| + 0, /* 10: STRUCT */ | |
| + 0, /* 11: UNION */ | |
| + 0, /* 12: ENUM */ | |
| + 0, /* 13: FUNKT */ | |
| + 0, /* 14: unused */ | |
| + 0, /* 15: unused */ | |
| +}; | |
| + | |
| +/* Names of all the registers. | |
| + * We can have 16 local variables per routine. Var 0 is always the C stack | |
| + * pointer, xp. All the others can be used by the compiler. xp doesn't actually | |
| + * appear in the register map, so we get 15 main registers. | |
| + */ | |
| + | |
| +char* regnames[] = { | |
| + "sp", /* vbcc doesn't use this, but we do */ | |
| + "xp", "r0", "r1", "r2", "r3", "r4", "r5", "r6", | |
| + "r7", "r8", "r9", "r10", "r11", "r12"}; | |
| +#define XP 1 | |
| +#define USERREG 2 | |
| + | |
| +/* The size of each register, in byes. */ | |
| + | |
| +zlong regsize[] = { | |
| + 0, | |
| + 2, 2, 2, 2, 2, 2, 2, 2, | |
| + 2, 2, 2, 2, 2, 2}; | |
| + | |
| +/* Type needed to store each register. */ | |
| + | |
| +struct Typ ityp = {INT}; | |
| +struct Typ* regtype[] = { | |
| + NULL, | |
| + &ityp, &ityp, &ityp, &ityp, &ityp, &ityp, &ityp, &ityp, | |
| + &ityp, &ityp, &ityp, &ityp, &ityp, &ityp}; | |
| + | |
| +/* These registers are those dedicated for use by the backend. These ones will | |
| + * not be used by the code generator. */ | |
| + | |
| +int regsa[] = { | |
| + 0, | |
| + 1, 0, 0, 0, 0, 0, 0, 0, | |
| + 0, 0, 0, 0, 0, 0}; | |
| + | |
| +/* Specifies which registers may be destroyed by function calls. As we're | |
| + * storing our registers in local variables so they're being automatically | |
| + * saved for us, none of them. | |
| + */ | |
| + | |
| +int regscratch[] = { | |
| + 0, | |
| + 0, 0, 0, 0, 0, 0, 0, 0, | |
| + 0, 0, 0, 0, 0, 0}; | |
| + | |
| +/* Default state for register parameter passing. */ | |
| + | |
| +struct reg_handle empty_reg_handle = | |
| + {USERREG}; | |
| + | |
| +/* Prefix for labels. */ | |
| + | |
| +static char* labelprefix = "L"; | |
| + | |
| +/* Name of the current module; used for generating unique names for statics and | |
| + * the constant pool. */ | |
| + | |
| +static char* modulename; | |
| + | |
| +/* Stack frame layout: | |
| + * | |
| + * -------------- | |
| + * Arg 4 (Arguments being passed to this function) | |
| + * Arg 3 | |
| + * Arg 2 | |
| + * Arg 1 | |
| + * -------------- xp + stackparamadjust + stackoffset | |
| + * Local 4 (This function's temp space) | |
| + * Local 3 | |
| + * Local 2 | |
| + * Local 1 | |
| + * -------------- xp + stackparamadjust | |
| + * Arg 2 (Arguments this function has pushed to pass | |
| + * Arg 1 to a called function) | |
| + * -------------- xp | |
| + * | |
| + * Any area may be zero in size. (Although stackoffset is always at least 2 for | |
| + * some inadequately explained reason.) | |
| + */ | |
| + | |
| +static int stackoffset; | |
| +static int stackparamadjust; | |
| + | |
| +/* Represents something the Z-machine can use as an instruction operand. */ | |
| + | |
| +struct zop { | |
| + int type; | |
| + union { | |
| + int reg; | |
| + zlong constant; | |
| + char* identifier; | |
| + } val; | |
| +}; | |
| + | |
| +enum { | |
| + ZOP_STACK, | |
| + ZOP_REG, | |
| + ZOP_CONSTANT, | |
| + ZOP_EXTERN, | |
| + ZOP_STATIC, | |
| + ZOP_CONSTANTADDR | |
| +}; | |
| + | |
| +/* Some useful zops. */ | |
| + | |
| +struct zop zop_zero = {ZOP_CONSTANT, {constant: 0}}; | |
| +struct zop zop_xp = {ZOP_REG, {reg: XP}}; | |
| +struct zop zop_stack = {ZOP_STACK, 0}; | |
| + | |
| +/* Temporaries used to store comparison register numbers. */ | |
| + | |
| +static struct zop compare1; | |
| +static struct zop compare2; | |
| + | |
| +/* Keeps track of whether we've emitted anything or not. Used to determine | |
| + * whether to emit the seperating ; or not. If it's 1, we haven't emitted | |
| + * anything. If it's -1, we're doing an array, so we need to emit a final (0) | |
| + * to finish it off if it's only one byte long. 0 for anything else. */ | |
| + | |
| +static int virgin = 1; | |
| + | |
| +/* The current variable we're emitting data for. */ | |
| + | |
| +struct variable { | |
| + int type; | |
| + union { | |
| + char* identifier; | |
| + int number; | |
| + } val; | |
| + zint offset; | |
| +}; | |
| + | |
| +struct variable currentvar; | |
| + | |
| +/* Inform can't emit variable references inside arrays. So when vbcc wants to | |
| + * put, say, the address of something in a global variable, we have to write it | |
| + * in later. A linked list of these structures keeps track of the items that | |
| + * need fixing up. */ | |
| + | |
| +struct fixup { | |
| + struct fixup* next; | |
| + struct variable identifier; | |
| + struct variable value; | |
| + zlong offset; | |
| +}; | |
| + | |
| +static struct fixup* fixuplist = NULL; | |
| + | |
| +/* 32-bit values are stored in a constant pool, for simplicity. It's kept track | |
| + * of in this linked list. */ | |
| + | |
| +struct constant { | |
| + struct constant* next; | |
| + int id; | |
| + zlong value; | |
| +}; | |
| + | |
| +static struct constant* constantlist = NULL; | |
| +static int constantnum = 0; | |
| + | |
| +/* The function we're currently compiling. */ | |
| + | |
| +static struct Var* function; | |
| + | |
| +/* Function prototypes. */ | |
| + | |
| +static void emit_add(FILE* fp, struct zop* q1, struct zop* q2, struct zop* z); | |
| +static void read_reg(FILE* fp, struct obj* obj, int typf, int reg); | |
| +static int addconstant(zlong value); | |
| + | |
| +/* Emit debugging info. */ | |
| + | |
| +static void debugemit(FILE* fp, char* fmt, ...) | |
| +{ | |
| + va_list ap; | |
| + | |
| + va_start(ap, fmt); | |
| + if (g_flags[5] & USEDFLAG) | |
| + vfprintf(fp, fmt, ap); | |
| + va_end(ap); | |
| +} | |
| + | |
| +/* Do we need to emit a ; before the next thing? */ | |
| + | |
| +static void reflower(FILE* fp) | |
| +{ | |
| + if (!virgin) | |
| + fprintf(fp, ";\n"); | |
| + if (virgin == -1) | |
| + { | |
| + if (currentvar.offset == 1) | |
| + fprintf(fp, "(0)"); | |
| + fprintf(fp, ";"); | |
| + } | |
| + virgin = 0; | |
| +} | |
| + | |
| +/* Extract the sign extended byte n of a value. */ | |
| + | |
| +static char xbyte(zlong val, int byte) | |
| +{ | |
| + val <<= (sizeof(val)*8) - (byte*8) - 8; | |
| + val >>= (sizeof(val)*8) - 8; | |
| + return (unsigned char) val; | |
| +} | |
| + | |
| +/* Extract the sign extended word n of a value. */ | |
| + | |
| +static zshort xword(zlong val, int word) | |
| +{ | |
| + val <<= (sizeof(val)*8) - (word*16) - 16; | |
| + val >>= (sizeof(val)*8) - 16; | |
| + return (zshort) val; | |
| +} | |
| + | |
| +/* Debug function: prints the text name of a type. */ | |
| + | |
| +static void dump_type(FILE* fp, int typf) | |
| +{ | |
| + switch (typf) | |
| + { | |
| + case VOID: fprintf(fp, "VOID"); break; | |
| + case CHAR: fprintf(fp, "CHAR"); break; | |
| + case SHORT: fprintf(fp, "SHORT"); break; | |
| + case INT: fprintf(fp, "INT"); break; | |
| + case LONG: fprintf(fp, "LONG"); break; | |
| + case POINTER: fprintf(fp, "POINTER"); break; | |
| + case STRUCT: fprintf(fp, "STRUCT"); break; | |
| + case ARRAY: fprintf(fp, "ARRAY"); break; | |
| + case UNION: fprintf(fp, "UNION"); break; | |
| + case FUNKT: fprintf(fp, "FUNKT"); break; | |
| + default: fprintf(fp, "unknown %X", typf); | |
| + } | |
| +} | |
| + | |
| +/* Debug function: outputs the obj. */ | |
| + | |
| +static void dump_obj(FILE* fp, struct obj* obj, int typf) | |
| +{ | |
| + int f = obj->flags & (KONST|REG|VAR|DREFOBJ|VARADR); | |
| + | |
| + if (f == 0) | |
| + { | |
| + fprintf(fp, "[]"); | |
| + return; | |
| + } | |
| + | |
| + if (f & DREFOBJ) | |
| + fprintf(fp, "*"); | |
| + | |
| + if (f & VARADR) | |
| + fprintf(fp, "&"); | |
| + | |
| + if (f == KONST) | |
| + { | |
| + switch (typf & NU) | |
| + { | |
| + case CHAR: | |
| + fprintf(fp, "[char #%d]", obj->val.vchar); | |
| + break; | |
| + | |
| + case UNSIGNED|CHAR: | |
| + fprintf(fp, "[uchar #%u]", obj->val.vuchar); | |
| + break; | |
| + | |
| + case SHORT: | |
| + fprintf(fp, "[short #%d]", obj->val.vshort); | |
| + break; | |
| + | |
| + case UNSIGNED|SHORT: | |
| + fprintf(fp, "[ushort #%u]", obj->val.vushort); | |
| + break; | |
| + | |
| + case INT: | |
| + fprintf(fp, "[int #%d]", obj->val.vint); | |
| + break; | |
| + | |
| + case UNSIGNED|INT: | |
| + fprintf(fp, "[uint #%d]", obj->val.vuint); | |
| + break; | |
| + | |
| + case LONG: | |
| + fprintf(fp, "[long #%d]", obj->val.vlong); | |
| + break; | |
| + | |
| + case UNSIGNED|LONG: | |
| + fprintf(fp, "[ulong #%u]", obj->val.vulong); | |
| + break; | |
| + | |
| + case FLOAT: | |
| + fprintf(fp, "[float #%04X]", obj->val.vfloat); | |
| + break; | |
| + | |
| + case DOUBLE: | |
| + fprintf(fp, "[double #%08X]", obj->val.vdouble); | |
| + break; | |
| + | |
| + case POINTER: | |
| + fprintf(fp, "[pointer #%04X]", obj->val.vpointer); | |
| + break; | |
| + } | |
| + } | |
| + else if (f == REG) | |
| + fprintf(fp, "[reg %s]", regnames[obj->reg]); | |
| + else if (f == (REG|DREFOBJ)) | |
| + fprintf(fp, "[deref reg %s]", regnames[obj->reg]); | |
| + //else if (f & VAR) | |
| + else | |
| + { | |
| + fprintf(fp, "[var "); | |
| + dump_type(fp, typf); | |
| + fprintf(fp, " %s", obj->v->identifier); | |
| + | |
| + if ((obj->v->storage_class == AUTO) || | |
| + (obj->v->storage_class == REGISTER)) | |
| + { | |
| + zlong offset = obj->v->offset; | |
| + //if (offset < 0) | |
| + // offset = -(offset+maxalign); | |
| + fprintf(fp, " at fp%+d", offset); | |
| + } | |
| + | |
| + fprintf(fp, "+%ld", obj->val.vlong); | |
| + | |
| + if (f & REG) | |
| + fprintf(fp, " in %s", regnames[obj->reg]); | |
| + fprintf(fp, "]"); | |
| + } | |
| +} | |
| + | |
| +/* Debug function: outputs the ic, as a comment. */ | |
| + | |
| +static void dump_ic(FILE* fp, struct IC* ic) | |
| +{ | |
| + char* p; | |
| + | |
| + if (!ic) | |
| + return; | |
| + | |
| + if (!(g_flags[4] & USEDFLAG)) | |
| + return; | |
| + | |
| + if (g_flags[2] & USEDFLAG) | |
| + fprintf(fp, "print \""); | |
| + else | |
| + fprintf(fp, "! "); | |
| + | |
| + switch (ic->code) | |
| + { | |
| + case ASSIGN: p = "ASSIGN"; break; | |
| + case OR: p = "OR"; break; | |
| + case XOR: p = "XOR"; break; | |
| + case AND: p = "AND"; break; | |
| + case LSHIFT: p = "LSHIFT"; break; | |
| + case RSHIFT: p = "RSHIFT"; break; | |
| + case ADD: p = "ADD"; break; | |
| + case SUB: p = "SUB"; break; | |
| + case MULT: p = "MULT"; break; | |
| + case DIV: p = "DIV"; break; | |
| + case MOD: p = "MOD"; break; | |
| + case KOMPLEMENT: p = "KOMPLEMENT"; break; | |
| + case MINUS: p = "MINUS"; break; | |
| + case ADDRESS: p = "ADDRESS"; break; | |
| + case CALL: p = "CALL"; break; | |
| + case CONVCHAR: p = "CONVCHAR"; break; | |
| + case CONVSHORT: p = "CONVSHORT"; break; | |
| + case CONVINT: p = "CONVINT"; break; | |
| + case CONVLONG: p = "CONVLONG"; break; | |
| + case CONVFLOAT: p = "CONVFLOAT"; break; | |
| + case CONVDOUBLE: p = "CONVDOUBLE"; break; | |
| + case CONVPOINTER: p = "CONVPOINTER"; break; | |
| + case CONVUCHAR: p = "CONVUCHAR"; break; | |
| + case CONVUSHORT: p = "CONVUSHORT"; break; | |
| + case CONVUINT: p = "CONVUINT"; break; | |
| + case CONVULONG: p = "CONVULONG"; break; | |
| + case ALLOCREG: p = "ALLOCREG"; break; | |
| + case FREEREG: p = "FREEREG"; break; | |
| + case COMPARE: p = "COMPARE"; break; | |
| + case TEST: p = "TEST"; break; | |
| + case LABEL: p = "LABEL"; break; | |
| + case BEQ: p = "BEQ"; break; | |
| + case BNE: p = "BNE"; break; | |
| + case BLT: p = "BLT"; break; | |
| + case BGT: p = "BGT"; break; | |
| + case BLE: p = "BLE"; break; | |
| + case BGE: p = "BGE"; break; | |
| + case BRA: p = "BRA"; break; | |
| + case PUSH: p = "PUSH"; break; | |
| + case ADDI2P: p = "ADDI2P"; break; | |
| + case SUBIFP: p = "SUBIFP"; break; | |
| + case SUBPFP: p = "SUBPFP"; break; | |
| + case GETRETURN: p = "GETRETURN"; break; | |
| + case SETRETURN: p = "SETRETURN"; break; | |
| + case MOVEFROMREG: p = "MOVEFROMREG"; break; | |
| + case MOVETOREG: p = "MOVETOREG"; break; | |
| + case NOP: p = "NOP"; break; | |
| + default: p = "???"; | |
| + } | |
| + | |
| + fprintf(fp, "%s ", p); | |
| + dump_type(fp, ic->typf); | |
| + fprintf(fp, " "); | |
| + | |
| + switch (ic->code) | |
| + { | |
| + case LABEL: | |
| + case BEQ: | |
| + case BNE: | |
| + case BLT: | |
| + case BGT: | |
| + case BLE: | |
| + case BGE: | |
| + case BRA: | |
| + fprintf(fp, "%d", ic->typf); | |
| + goto epilogue; | |
| + } | |
| + | |
| + dump_obj(fp, &ic->q1, ic->typf); | |
| + fprintf(fp, " "); | |
| + dump_obj(fp, &ic->q2, ic->typf); | |
| + fprintf(fp, " -> "); | |
| + dump_obj(fp, &ic->z, ic->typf); | |
| + | |
| +epilogue: | |
| + if (g_flags[2] & USEDFLAG) | |
| + fprintf(fp, "^\";\n"); | |
| + else | |
| + fprintf(fp, "\n"); | |
| +} | |
| + | |
| +/* Initialise the code generator. This is called once. Returns 0 if things go | |
| + * wrong. */ | |
| + | |
| +int init_cg(void) | |
| +{ | |
| + modulename = g_flags_val[0].p; | |
| + if (!modulename) | |
| + modulename = ""; | |
| + return 1; | |
| +} | |
| + | |
| +/* Returns the register in which variables of type typ are returned (or 0 if it | |
| + * can't be done). */ | |
| + | |
| +int freturn(struct Typ *typ) | |
| +{ | |
| + int s = sizetab[typ->flags & NQ]; | |
| + if ((typ->flags & NQ) == VOID) | |
| + return USERREG; | |
| + if ((s <= sizetab[INT]) && (s > 0)) | |
| + return USERREG; | |
| + return 0; | |
| +} | |
| + | |
| +/* Returns 1 if register reg can store variables of type typ. mode is set | |
| + * if the register is a pointer and the register is going to be dereferenced. | |
| + */ | |
| + | |
| +int regok(int reg, int typf, int mode) | |
| +{ | |
| + int s = sizetab[typf & NQ]; | |
| + if ((typf & NQ) == VOID) | |
| + return 1; | |
| + if ((s <= sizetab[INT]) && (s > 0)) | |
| + return 1; | |
| + return 0; | |
| +} | |
| + | |
| +/* Returns zero if the IC ic can be safely executed without danger of | |
| + * exceptions or similar things; for example, divisions or pointer dereferences | |
| + * are dangerous. This is used by the optimiser for code reordering. | |
| + */ | |
| + | |
| +int dangerous_IC(struct IC *ic) | |
| +{ | |
| + /* Check for dereferences. */ | |
| + | |
| + if ((ic->q1.flags & DREFOBJ) || | |
| + (ic->q2.flags & DREFOBJ) || | |
| + (ic->z.flags & DREFOBJ)) | |
| + return 0; | |
| + | |
| + /* Division or modulo? */ | |
| + | |
| + if ((ic->code == DIV) || | |
| + (ic->code == MOD)) | |
| + return 0; | |
| + | |
| + /* Safe, as far as we can tell. */ | |
| + | |
| + return 1; | |
| +} | |
| + | |
| +/* Returns zero if the code for converting type p->ntyp to type typ is a noop. | |
| + */ | |
| + | |
| +int must_convert(np p, int typ) | |
| +{ | |
| + int oldtype = p->ntyp->flags & NQ; | |
| + int newtype = typ & NQ; | |
| + | |
| + /* ints and shorts are equivalent. */ | |
| + | |
| + if (oldtype == SHORT) | |
| + oldtype = INT; | |
| + if (newtype == SHORT) | |
| + newtype = INT; | |
| + | |
| + /* Both the same type? */ | |
| + | |
| + if (oldtype == newtype) | |
| + return 0; | |
| + | |
| +#if 0 | |
| + /* Converting two basic integers? */ | |
| + | |
| + if ((oldtype <= INT) && (newtype <= INT)) | |
| + { | |
| + /* ... but char to short needs an AND. */ | |
| + | |
| + if ((oldtype == CHAR) && (newtype != CHAR)) | |
| + return 1; | |
| + return 0; | |
| + } | |
| +#endif | |
| + | |
| + /* Pointer to/from int? */ | |
| + | |
| + if (((oldtype == INT) || (oldtype == POINTER)) && | |
| + ((newtype == INT) || (newtype == POINTER))) | |
| + return 0; | |
| + | |
| + /* Everything else needs code. */ | |
| + | |
| + return 1; | |
| +} | |
| + | |
| +/* Ensure the output is aligned. A noop on the Z-machine. */ | |
| + | |
| +void gen_align(FILE* fp, zlong align) | |
| +{ | |
| +} | |
| + | |
| +/* Generate the label part of a variable definition. */ | |
| + | |
| +void gen_var_head(FILE* fp, struct Var* var) | |
| +{ | |
| + if (var->storage_class == EXTERN) | |
| + debugemit(fp, "! Var %s %X\n", var->identifier, var->flags); | |
| + if (var->storage_class == STATIC) | |
| + debugemit(fp, "! Var static %ld %s %X\n", var->offset, var->identifier, var->flags); | |
| + | |
| + /* We only want to emit records for genuinely defined variables. For | |
| + * some reason, TENTATIVE is defined for some of this. */ | |
| + | |
| + if ((var->storage_class == EXTERN) && | |
| + !(var->flags & DEFINED) && | |
| + !(var->flags & TENTATIVE)) | |
| + return; | |
| + | |
| + reflower(fp); | |
| + virgin = -1; | |
| + switch (var->storage_class) | |
| + { | |
| + case EXTERN: | |
| + /* This doesn't actually mean external linkage; it | |
| + * means a non-static global that may be referenced | |
| + * externally. */ | |
| + fprintf(fp, "Array _%s ->\n", | |
| + var->identifier); | |
| + currentvar.type = EXTERN; | |
| + currentvar.val.identifier = strdup(var->identifier); | |
| + currentvar.offset = 0; | |
| + break; | |
| + | |
| + case STATIC: | |
| + fprintf(fp, "Array STATIC_%s_%ld ->\n", | |
| + modulename, var->offset); | |
| + currentvar.type = STATIC; | |
| + currentvar.val.number = var->offset; | |
| + currentvar.offset = 0; | |
| + break; | |
| + } | |
| +} | |
| + | |
| +/* Emit a certain number of bytes of bss data. No bss on the Z-machine, | |
| + * remember. */ | |
| + | |
| +void gen_ds(FILE *fp, zlong size, struct Typ *typ) | |
| +{ | |
| + fprintf(fp, " %ld\n", size); | |
| + currentvar.offset += size; | |
| +} | |
| + | |
| +/* Emit a certain number of bytes of initialised data. */ | |
| + | |
| +void gen_dc(FILE *fp, int typf, struct const_list *p) | |
| +{ | |
| + switch (typf & NQ) | |
| + { | |
| + case CHAR: | |
| + fprintf(fp, " (%d)\n", | |
| + p->val.vuchar); | |
| + currentvar.offset += 1; | |
| + break; | |
| + | |
| + case SHORT: | |
| + case INT: | |
| + reallyanint: | |
| + fprintf(fp, " (%d) (%d)\n", | |
| + xbyte(p->val.vint, 1), | |
| + xbyte(p->val.vint, 0)); | |
| + currentvar.offset += 2; | |
| + break; | |
| + | |
| + case LONG: | |
| + fprintf(fp, " (%d) (%d) (%d) (%d)\n", | |
| + xbyte(p->val.vlong, 3), | |
| + xbyte(p->val.vlong, 2), | |
| + xbyte(p->val.vlong, 1), | |
| + xbyte(p->val.vlong, 0)); | |
| + currentvar.offset += 4; | |
| + break; | |
| + | |
| + case POINTER: | |
| + if (!p->tree) | |
| + goto reallyanint; | |
| + { | |
| + struct fixup* fixup = malloc(sizeof(struct fixup)); | |
| + struct obj* obj = &p->tree->o; | |
| + fixup->next = fixuplist; | |
| + fixuplist = fixup; | |
| + fixup->identifier = currentvar; | |
| + | |
| + switch (obj->v->storage_class) | |
| + { | |
| + case EXTERN: | |
| + fixup->value.type = EXTERN; | |
| + fixup->value.val.identifier = strdup(obj->v->identifier); | |
| + break; | |
| + | |
| + case STATIC: | |
| + fixup->value.type = STATIC; | |
| + fixup->value.val.number = obj->v->offset; | |
| + break; | |
| + | |
| + default: | |
| + ierror(0); | |
| + } | |
| + fixup->value.offset = 0; | |
| + fixup->offset = obj->val.vlong; | |
| + fprintf(fp, " (0) (0)\n"); | |
| + currentvar.offset += 2; | |
| + } | |
| + break; | |
| + | |
| + default: | |
| + printf("type %d\n", typf); | |
| + ierror(0); | |
| + } | |
| +} | |
| + | |
| +/* Returns the offset of the (STATIC or AUTO) given object. */ | |
| + | |
| +zlong voff(struct obj* obj) | |
| +{ | |
| + zlong offset = obj->v->offset; | |
| + if (offset < 0) | |
| + offset = stackparamadjust + stackoffset - offset - maxalign; | |
| + else | |
| + offset += stackparamadjust; | |
| + | |
| + offset += obj->val.vlong; | |
| + return offset; | |
| +} | |
| + | |
| +/* When a varargs function is called, we need to find where the parameters are | |
| + * on the stack in order to make the __va_start magic variable work. This | |
| + * function does that. */ | |
| + | |
| +static int find_varargs(void) | |
| +{ | |
| + int offset = 0; | |
| + struct reg_handle rh = empty_reg_handle; | |
| + struct struct_declaration* sd = function->vtyp->exact; | |
| + int stackalign; | |
| + int i; | |
| + | |
| + for (i=0; i<sd->count; i++) | |
| + { | |
| + /* Ignore the parameter if it's been assigned a register. */ | |
| + | |
| + if ((*sd->sl)[i].reg != 0) | |
| + continue; | |
| + | |
| + /* void shouldn't happen. */ | |
| + | |
| + if (((*sd->sl)[i].styp->flags & NQ) == VOID) | |
| + ierror(0); | |
| + | |
| + /* Does the backend want to assign it to a register? */ | |
| + | |
| + if (reg_parm(&rh, (*sd->sl)[i].styp, 0)) | |
| + continue; | |
| + | |
| + /* Add on the size of this parameter. */ | |
| + | |
| + offset += sizetab[(*sd->sl)[i].styp->flags & NQ]; | |
| + | |
| + /* Stack align. */ | |
| + | |
| + stackalign = align[(*sd->sl)[i].styp->flags & NQ]; | |
| + offset = ((offset+1) / stackalign) * stackalign; | |
| + } | |
| + | |
| + return (offset + stackoffset); | |
| +} | |
| + | |
| +/* Output the name of a global. */ | |
| + | |
| +static void emit_identifier(FILE* fp, struct obj* obj) | |
| +{ | |
| + switch (obj->v->storage_class) | |
| + { | |
| + case STATIC: | |
| + fprintf(fp, "STATIC_%s_%ld", | |
| + modulename, obj->v->offset); | |
| + break; | |
| + | |
| + case EXTERN: | |
| + fprintf(fp, "_%s", obj->v->identifier); | |
| + break; | |
| + | |
| + default: | |
| + ierror(0); | |
| + } | |
| +} | |
| + | |
| +/* Save a register. */ | |
| + | |
| +static void write_reg(FILE* fp, struct obj* obj, int typf, int reg) | |
| +{ | |
| + int flags = obj->flags & | |
| + (KONST|REG|VAR|DREFOBJ|VARADR); | |
| + | |
| + /* Constant? */ | |
| + | |
| + if (flags == KONST) | |
| + ierror(0); | |
| + | |
| + /* Dereference? */ | |
| + | |
| + if (flags & DREFOBJ) | |
| + goto dereference; | |
| + | |
| + /* Register? */ | |
| + | |
| + if ((flags == REG) || | |
| + ((flags & VAR) && (flags & REG) && (obj->v->storage_class == AUTO)) || | |
| + ((flags & VAR) && (flags & REG) && (obj->v->storage_class == REGISTER))) | |
| + { | |
| + if (flags & DREFOBJ) | |
| + fprintf(fp, "\t@store%c %s 0 %s;\n", | |
| + ((typf & NQ) == CHAR) ? 'b' : 'w', | |
| + regnames[obj->reg], regnames[reg]); | |
| + else | |
| + { | |
| + struct zop in; | |
| + struct zop out; | |
| + in.type = ZOP_REG; | |
| + in.val.reg = reg; | |
| + out.type = ZOP_REG; | |
| + out.val.reg = obj->reg; | |
| + emit_add(fp, &in, &zop_zero, &out); | |
| + } | |
| +#if 0 | |
| + fprintf(fp, "\t@add %s 0 -> %s;\n", | |
| + regnames[reg], regnames[obj->reg]); | |
| +#endif | |
| + return; | |
| + } | |
| + | |
| + /* It must be a variable. */ | |
| + | |
| + switch (obj->v->storage_class) | |
| + { | |
| + case AUTO: | |
| + case REGISTER: /* Local variable */ | |
| + { | |
| + zlong offset = voff(obj); | |
| + | |
| + if ((typf & NQ) == CHAR) | |
| + fprintf(fp, "\t@storeb xp 0%+ld %s;\n", | |
| + offset, regnames[reg]); | |
| + else | |
| + { | |
| + if (offset & 1) | |
| + { | |
| + struct zop c; | |
| + c.type = ZOP_CONSTANT; | |
| + c.val.constant = offset; | |
| + emit_add(fp, &zop_xp, &c, &zop_stack); | |
| + //fprintf(fp, "\t@add xp 0%+ld -> sp;\n", offset); | |
| + fprintf(fp, "\t@storew sp 0 %s;\n", regnames[reg]); | |
| + } | |
| + else | |
| + fprintf(fp, "\t@storew xp 0%+ld %s;\n", | |
| + offset >> 1, regnames[reg]); | |
| + } | |
| + return; | |
| + } | |
| + | |
| + case EXTERN: | |
| + case STATIC: | |
| + /* Dereference object. */ | |
| + | |
| + if ((typf & NQ) == CHAR) | |
| + { | |
| + fprintf(fp, "\t@storeb "); | |
| + emit_identifier(fp, obj); | |
| + fprintf(fp, " 0%+ld %s;\n", | |
| + obj->val.vlong, regnames[reg]); | |
| + } | |
| + else | |
| + { | |
| + if (obj->val.vlong & 1) | |
| + { | |
| + fprintf(fp, "\t@add "); | |
| + emit_identifier(fp, obj); | |
| + fprintf(fp, " 0%+ld -> sp;\n", | |
| + obj->val.vlong); | |
| + fprintf(fp, "\t@storew sp 0 %s;\n", | |
| + regnames[reg]); | |
| + } | |
| + else | |
| + { | |
| + fprintf(fp, "\t@storew "); | |
| + emit_identifier(fp, obj); | |
| + fprintf(fp, " 0%+ld %s;\n", | |
| + obj->val.vlong >> 1, regnames[reg]); | |
| + } | |
| + } | |
| + return; | |
| +#if 0 | |
| + case EXTERN: /* External linkage */ | |
| + if ((typf & NQ) == CHAR) | |
| + fprintf(fp, "\t@storeb _%s 0%+ld %s;\n", | |
| + obj->v->identifier, offset, regnames[reg]); | |
| + else | |
| + { | |
| + | |
| + fprintf(fp, "\t@storew _%s 0 %s;\n", | |
| + obj->v->identifier, regnames[reg]); | |
| + return; | |
| + | |
| + case STATIC: /* Static global */ | |
| + if ((typf & NQ) == CHAR) | |
| + fprintf(fp, "\t@storeb STATIC_%s_%ld 0%+ld %s;\n", | |
| + modulename, obj->v->offset, offset, regnames[reg]); | |
| + else | |
| + fprintf(fp, "\t@storew STATIC_%s_%ld 0 %s;\n", | |
| + modulename, obj->v->offset, regnames[reg]); | |
| + return; | |
| +#endif | |
| + | |
| + default: | |
| + ierror(0); | |
| + } | |
| + | |
| + ierror(0); // Not reached | |
| +dereference: | |
| + /* These are a *pain*. | |
| + * | |
| + * The first thing we need to do is to read the old contents of the | |
| + * memory cell, to work out the address we need to write to; and then | |
| + * do the write. Hurray for the Z-machine stack. */ | |
| + | |
| + obj->flags &= ~DREFOBJ; | |
| + read_reg(fp, obj, POINTER, 0); | |
| + fprintf(fp, "\t@store%c sp 0 %s;\n", | |
| + ((typf & NQ) == CHAR) ? 'b' : 'w', | |
| + regnames[reg]); | |
| +} | |
| + | |
| +/* Move one register to another register. */ | |
| + | |
| +static void move_reg(FILE* fp, int reg1, int reg2) | |
| +{ | |
| + struct zop r1; | |
| + struct zop r2; | |
| + r1.type = ZOP_REG; | |
| + r1.val.reg = reg1; | |
| + r2.type = ZOP_REG; | |
| + r2.val.reg = reg2; | |
| + emit_add(fp, &r1, &zop_zero, &r2); | |
| +} | |
| +/* Load a value into a zop. */ | |
| + | |
| +static void read_reg(FILE* fp, struct obj* obj, int typf, int reg) | |
| +{ | |
| + int flags = obj->flags & | |
| + (KONST|REG|VAR|DREFOBJ|VARADR); | |
| + | |
| + /* The only thing you can do with a function is to take the address of | |
| + * it. */ | |
| + | |
| + if ((typf & NQ) == FUNKT) | |
| + flags &= ~DREFOBJ & ~VARADR; | |
| + | |
| + /* Is this a memory dereference? */ | |
| + | |
| + if (flags & DREFOBJ) | |
| + goto dereference; | |
| + | |
| + /* Constant? */ | |
| + | |
| + if (flags == KONST) | |
| + { | |
| + struct zop c; | |
| + struct zop r; | |
| + c.type = ZOP_CONSTANT; | |
| + //fprintf(fp, "\t@add "); | |
| + switch (typf & NQ) | |
| + { | |
| + case CHAR: c.val.constant = obj->val.vchar; break; | |
| + case UNSIGNED|CHAR: c.val.constant = obj->val.vuchar; break; | |
| + case SHORT: c.val.constant = obj->val.vshort; break; | |
| + case UNSIGNED|SHORT: c.val.constant = obj->val.vushort; break; | |
| + case POINTER: c.val.constant = obj->val.vpointer; break; | |
| + case INT: c.val.constant = obj->val.vint; break; | |
| + case UNSIGNED|INT: c.val.constant = obj->val.vuint; break; | |
| + default: | |
| + ierror(typf); | |
| + } | |
| + r.type = ZOP_REG; | |
| + r.val.reg = reg; | |
| + emit_add(fp, &c, &zop_zero, &r); | |
| + //fprintf(fp, " 0 -> %s;\n", regnames[reg]); | |
| + } | |
| + else if (flags == REG) /* Register? */ | |
| + { | |
| + move_reg(fp, obj->reg, reg); | |
| + //fprintf(fp, "\t@add %s 0 -> %s;\n", regnames[obj->reg], regnames[reg]); | |
| + } | |
| + else if ((flags & REG) && ((typf & NQ) == FUNKT)) /* Function pointer? */ | |
| + { | |
| + move_reg(fp, obj->reg, reg); | |
| + //fprintf(fp, "\t@add %s 0 -> %s;\n", regnames[obj->reg], regnames[reg]); | |
| + } | |
| + else | |
| + { | |
| + /* It must be a variable. */ | |
| + | |
| + switch (obj->v->storage_class) | |
| + { | |
| + case AUTO: | |
| + case REGISTER: /* Local variable */ | |
| + if (flags & VARADR) | |
| + { | |
| + fprintf(fp, "\t@add xp 0%+ld -> %s;\n", | |
| + voff(obj), regnames[reg]); | |
| + } | |
| + else if (flags & REG) | |
| + { | |
| + move_reg(fp, obj->reg, reg); | |
| + //fprintf(fp, "\t@add %s 0 -> %s;\n", | |
| + // regnames[obj->reg], regnames[reg]); | |
| + } | |
| + else | |
| + { | |
| + zlong offset = voff(obj); | |
| + | |
| + if ((typf & NQ) == CHAR) | |
| + fprintf(fp, "\t@loadb xp 0%+ld -> %s;\n", | |
| + offset, regnames[reg]); | |
| + else | |
| + { | |
| + if (offset & 1) | |
| + { | |
| + fprintf(fp, "\t@add xp 0%+ld -> sp;\n", offset); | |
| + fprintf(fp, "\t@loadw sp 0 -> %s;\n", regnames[reg]); | |
| + } | |
| + else | |
| + fprintf(fp, "\t@loadw xp 0%+ld -> %s;\n", | |
| + offset >> 1, regnames[reg]); | |
| + } | |
| + } | |
| + break; | |
| + | |
| + case STATIC: | |
| + case EXTERN: /* Global variable. Implicit dereference, | |
| + with the offset in obj->val.vlong. */ | |
| + | |
| + /* ...but functions are never dereferenced. */ | |
| + | |
| + if ((flags & VARADR) || | |
| + ((typf & NQ) == FUNKT)) | |
| + { | |
| + /* Fetch address of object. */ | |
| + | |
| + fprintf(fp, "\t@add "); | |
| + emit_identifier(fp, obj); | |
| + fprintf(fp, " 0%+ld -> %s;\n", | |
| + obj->val.vlong, regnames[reg]); | |
| + } | |
| + else if (strcmp(obj->v->identifier, "__va_start") == 0) | |
| + { | |
| + fprintf(fp, "\t@add xp 0%+ld -> %s;\n", | |
| + find_varargs(), regnames[reg]); | |
| + } | |
| + else | |
| + { | |
| + /* Dereference object. */ | |
| + | |
| + if ((typf & NQ) == CHAR) | |
| + { | |
| + fprintf(fp, "\t@loadb "); | |
| + emit_identifier(fp, obj); | |
| + fprintf(fp, " 0%+ld -> %s;\n", | |
| + obj->val.vlong, regnames[reg]); | |
| + } | |
| + else | |
| + { | |
| + if (obj->val.vlong & 1) | |
| + { | |
| + fprintf(fp, "\t@add "); | |
| + emit_identifier(fp, obj); | |
| + fprintf(fp, " 0%+ld -> sp;\n", | |
| + obj->val.vlong); | |
| + fprintf(fp, "\t@loadw sp 0 -> %s;\n", | |
| + regnames[reg]); | |
| + } | |
| + else | |
| + { | |
| + fprintf(fp, "\t@loadw "); | |
| + emit_identifier(fp, obj); | |
| + fprintf(fp, " 0%+ld -> %s;\n", | |
| + obj->val.vlong >> 1, regnames[reg]); | |
| + } | |
| + } | |
| + } | |
| + break; | |
| + | |
| + default: | |
| + ierror(obj->v->storage_class); | |
| + } | |
| + } | |
| + return; | |
| + | |
| +dereference: | |
| + /* Do we need to dereference the thing we just fetched? */ | |
| + | |
| + /* Fetch the value to dereference. */ | |
| + obj->flags &= ~DREFOBJ; | |
| + read_reg(fp, obj, POINTER, 0); | |
| + | |
| + if (flags & DREFOBJ) | |
| + { | |
| + switch (typf & NQ) | |
| + { | |
| + case CHAR: | |
| + fprintf(fp, "\t@loadb sp 0 -> %s;\n", | |
| + regnames[reg], regnames[reg]); | |
| + break; | |
| + | |
| + case SHORT: | |
| + case INT: | |
| + case POINTER: | |
| + case FUNKT: | |
| + fprintf(fp, "\t@loadw sp 0 -> %s;\n", | |
| + regnames[reg], regnames[reg]); | |
| + break; | |
| + | |
| + default: | |
| + ierror(typf & NQ); | |
| + } | |
| + } | |
| +} | |
| + | |
| +/* Returns the zop to use for an input parameter, pushing that parameter onto | |
| + * the stack if necessary. */ | |
| + | |
| +static void push_value(FILE* fp, struct obj* obj, int typf, struct zop* op) | |
| +{ | |
| + int flags = obj->flags & | |
| + (KONST|REG|VAR|DREFOBJ|VARADR); | |
| + | |
| + if (flags == KONST) | |
| + { | |
| + op->type = ZOP_CONSTANT; | |
| + switch (typf & NU) | |
| + { | |
| + case CHAR: op->val.constant = obj->val.vchar; break; | |
| + case UNSIGNED|CHAR: op->val.constant = obj->val.vuchar; break; | |
| + case SHORT: op->val.constant = obj->val.vshort; break; | |
| + case UNSIGNED|SHORT: op->val.constant = obj->val.vushort; break; | |
| + case INT: op->val.constant = obj->val.vint; break; | |
| + case UNSIGNED|INT: op->val.constant = obj->val.vuint; break; | |
| + case POINTER: op->val.constant = obj->val.vpointer; break; | |
| + default: | |
| + fprintf(fp, "XXX !!! bad konst type %X\n", typf); | |
| + } | |
| + return; | |
| + } | |
| + | |
| + /* The only thing you can do with a function is to take the address of it. */ | |
| + | |
| + if ((typf & NQ) == FUNKT) | |
| + flags &= ~DREFOBJ & ~VARADR; | |
| + | |
| + /* This is used by the long code. The longop functions can only operate | |
| + * on pointers to longs; so if we need to pass in a constant, we have | |
| + * to stash it on the stack and return a pointer. */ | |
| + | |
| + if (flags == (KONST|VARADR)) | |
| + { | |
| + op->type = ZOP_CONSTANTADDR; | |
| + op->val.constant = addconstant(obj->val.vlong); | |
| + return; | |
| + } | |
| + | |
| + if (flags == REG) | |
| + { | |
| + debugemit(fp, "! zop reg %d\n", obj->reg); | |
| + op->type = ZOP_REG; | |
| + op->val.reg = obj->reg; | |
| + return; | |
| + } | |
| + | |
| + if ((flags == (VAR|REG)) && | |
| + ((obj->v->storage_class == AUTO) || | |
| + (obj->v->storage_class == REGISTER))) | |
| + { | |
| + debugemit(fp, "! zop var reg %d\n", obj->reg); | |
| + op->type = ZOP_REG; | |
| + op->val.reg = obj->reg; | |
| + return; | |
| + } | |
| + | |
| + if ((flags == (VAR|VARADR)) && | |
| + (obj->v->storage_class == EXTERN) && | |
| + (obj->v->offset == 0)) | |
| + { | |
| + debugemit(fp, "! zop varaddr extern %s\n", obj->v->identifier); | |
| + op->type = ZOP_EXTERN; | |
| + op->val.identifier = obj->v->identifier; | |
| + return; | |
| + } | |
| + | |
| + if ((flags == (VAR|VARADR)) && | |
| + (obj->v->storage_class == STATIC) && | |
| + (obj->v->offset == 0)) | |
| + { | |
| + debugemit(fp, "! zop varaddr static %ld\n", obj->v->offset); | |
| + op->type = ZOP_STATIC; | |
| + op->val.constant = obj->v->offset; | |
| + return; | |
| + } | |
| + | |
| + if ((flags & VAR) && | |
| + ((obj->v->vtyp->flags & NQ) == FUNKT)) | |
| + { | |
| + if (obj->v->storage_class == EXTERN) | |
| + { | |
| + op->type = ZOP_EXTERN; | |
| + op->val.identifier = obj->v->identifier; | |
| + } | |
| + else | |
| + { | |
| + op->type = ZOP_STATIC; | |
| + op->val.constant = obj->v->offset; | |
| + } | |
| + return; | |
| + } | |
| + | |
| + read_reg(fp, obj, typf, 0); | |
| + op->type = ZOP_STACK; | |
| +} | |
| + | |
| +/* Same as push_value(), but returns a zop for the *address* of the object, not | |
| + * the object itself. Used a lot by the long code. */ | |
| + | |
| +static void push_addrof(FILE* fp, struct obj* obj, int typf, struct zop* op) | |
| +{ | |
| + if (obj->flags & DREFOBJ) | |
| + obj->flags &= ~DREFOBJ; | |
| + else | |
| + obj->flags |= VARADR; | |
| + push_value(fp, obj, POINTER, op); | |
| +} | |
| + | |
| +/* Returns the zop to use for an output parameter. Unlike push_value, this does | |
| + * not emit a pop; that must be done later, if the return parameter is zero. */ | |
| + | |
| +static void pop_value(FILE* fp, struct obj* obj, int typf, struct zop* op) | |
| +{ | |
| + int flags = obj->flags & | |
| + (KONST|REG|VAR|DREFOBJ|VARADR); | |
| + | |
| + /* We don't even *try* to handle dereferences here. */ | |
| + | |
| + if (flags & DREFOBJ) | |
| + goto stack; | |
| + | |
| + if (flags == REG) | |
| + goto reg; | |
| + | |
| + if ((flags == (VAR|REG)) && | |
| + ((obj->v->storage_class == AUTO) || | |
| + (obj->v->storage_class == REGISTER))) | |
| + goto reg; | |
| + | |
| +stack: | |
| + op->type = ZOP_STACK; | |
| + return; | |
| + | |
| +reg: | |
| + op->type = ZOP_REG; | |
| + op->val.reg = obj->reg; | |
| +} | |
| + | |
| +/* Writes code for a zop. */ | |
| + | |
| +static void emit_zop(FILE* fp, struct zop* op) | |
| +{ | |
| + switch (op->type) | |
| + { | |
| + case ZOP_STACK: | |
| + fprintf(fp, "sp"); | |
| + return; | |
| + | |
| + case ZOP_REG: | |
| + fprintf(fp, "%s", regnames[op->val.reg]); | |
| + return; | |
| + | |
| + case ZOP_CONSTANT: | |
| + fprintf(fp, "0%+ld", (zshort)op->val.constant); | |
| + return; | |
| + | |
| + case ZOP_EXTERN: | |
| + fprintf(fp, "_%s", op->val.identifier); | |
| + return; | |
| + | |
| + case ZOP_STATIC: | |
| + fprintf(fp, "STATIC_%s_%ld", | |
| + modulename, op->val.constant); | |
| + return; | |
| + | |
| + case ZOP_CONSTANTADDR: | |
| + fprintf(fp, "CONSTANT_%s_%ld", | |
| + modulename, op->val.constant); | |
| + return; | |
| + | |
| + default: | |
| + ierror(op->type); | |
| + } | |
| +} | |
| + | |
| +/* This is used in conjunction with pop_value(). pop_value() returns a zop that | |
| + * represents the return value for a function. If that return value is the | |
| + * stack, the value on the stack needs to be written back into memory. That's | |
| + * what this function does. */ | |
| + | |
| +static void fin_zop(FILE* fp, struct obj* obj, int typf, struct zop* op) | |
| +{ | |
| + switch (op->type) | |
| + { | |
| + case ZOP_STACK: | |
| + write_reg(fp, obj, typf, 0); | |
| + return; | |
| + | |
| + case ZOP_REG: | |
| + return; | |
| + | |
| + default: | |
| + ierror(0); | |
| + } | |
| +} | |
| + | |
| +/* Emit a basic ADD instruction. | |
| + * This routine tests for all the various special cases, of which there are | |
| + * many, and attempts to produce optimal code. | |
| + */ | |
| + | |
| +static void emit_add(FILE* fp, struct zop* q1, struct zop* q2, struct zop* z) | |
| +{ | |
| + /* Sometimes we get ZOP_REG with reg=0. This actually means the stack. */ | |
| + | |
| + if ((q1->type == ZOP_REG) && (q1->val.reg == 0)) | |
| + q1 = &zop_stack; | |
| + if ((q2->type == ZOP_REG) && (q2->val.reg == 0)) | |
| + q2 = &zop_stack; | |
| + if ((z->type == ZOP_REG) && (z->val.reg == 0)) | |
| + z = &zop_stack; | |
| + | |
| + /* If q2 is a constant and 0, then this might be a register move of | |
| + * some kind. */ | |
| + | |
| + if ((q2->type == ZOP_CONSTANT) && (q2->val.constant == 0)) | |
| + { | |
| + /* Left is a register? */ | |
| + if (q1->type == ZOP_REG) | |
| + { | |
| + /* Right is a register? */ | |
| + if (z->type == ZOP_REG) | |
| + { | |
| + /* They're the *same* register? */ | |
| + if (q1->val.reg == z->val.reg) | |
| + { | |
| + /* No code need be emitted. */ | |
| + return; | |
| + } | |
| + | |
| + /* Emit a @store instruction. Unfortunately, I | |
| + * can't work out the syntax for Inform's | |
| + * @store opcode, so we emit a high-level | |
| + * assignment instead and let Inform work it | |
| + * out. */ | |
| + | |
| + fprintf(fp, "\t"); | |
| + emit_zop(fp, z); | |
| + fprintf(fp, " = "); | |
| + emit_zop(fp, q1); | |
| + fprintf(fp, ";\n"); | |
| + return; | |
| + } | |
| + | |
| + /* Right is the stack? */ | |
| + if (z->type == ZOP_STACK) | |
| + { | |
| + /* We're pushing the single parameter onto the | |
| + * stack. */ | |
| + | |
| + fprintf(fp, "\t@push "); | |
| + emit_zop(fp, q1); | |
| + fprintf(fp, ";\n"); | |
| + return; | |
| + } | |
| + } | |
| + | |
| + /* Left is the stack? */ | |
| + if (q1->type == ZOP_STACK) | |
| + { | |
| + /* Right is a register? */ | |
| + if (z->type == ZOP_REG) | |
| + { | |
| + /* We're popping the single parameter off the | |
| + * stack. */ | |
| + | |
| + fprintf(fp, "\t@pull "); | |
| + emit_zop(fp, z); | |
| + fprintf(fp, ";\n"); | |
| + return; | |
| + } | |
| + } | |
| + } | |
| + | |
| + /* Fall back on an ordinary @add. */ | |
| + | |
| + fprintf(fp, "\t@add "); | |
| + emit_zop(fp, q1); | |
| + fprintf(fp, " "); | |
| + emit_zop(fp, q2); | |
| + fprintf(fp, " -> "); | |
| + emit_zop(fp, z); | |
| + fprintf(fp, ";\n"); | |
| +} | |
| + | |
| +/* Copy a value from one zop to another. This is not quite as simple as you | |
| + * might think, because there are a number of optimisation cases to take into | |
| + * account. | |
| + * | |
| + * NOTE: for simplicity, this function will never emit just a single | |
| + * instruction --- the assignment is always done via the stack. FIXME. */ | |
| + | |
| +static void move_value(FILE* fp, struct obj* q1o, struct obj* zo, int typf) | |
| +{ | |
| + struct zop q1; | |
| + struct zop z; | |
| + | |
| + pop_value(fp, zo, typf, &z); | |
| + push_value(fp, q1o, typf, &q1); | |
| + debugemit(fp, "! L=%d R=%d\n", q1.type, z.type); | |
| + /* In all cases except when push_value() and fin_zop() *both* emit | |
| + * code, we need to insert an assignment here. As they only emit code | |
| + * in the ZOP_STACK case... */ | |
| + if ((q1.type != ZOP_STACK) || (z.type != ZOP_STACK)) | |
| + { | |
| + emit_add(fp, &q1, &zop_zero, &z); | |
| +#if 0 | |
| + fprintf(fp, "\t@add "); | |
| + emit_zop(fp, &q1); | |
| + fprintf(fp, " 0 -> "); | |
| + emit_zop(fp, &z); | |
| + fprintf(fp, ";\n"); | |
| +#endif | |
| + } | |
| + fin_zop(fp, zo, typf, &z); | |
| +} | |
| + | |
| +/* Copy a 32-bit value from one obj to another. */ | |
| + | |
| +static void move_long_value(FILE* fp, struct obj* q1, struct obj* z, int typf) | |
| +{ | |
| + int flags = q1->flags & | |
| + (KONST|REG|VAR|DREFOBJ|VARADR); | |
| + struct zop q1z; | |
| + struct zop zz; | |
| + | |
| + if (flags == KONST) | |
| + { | |
| + int hi = xword(q1->val.vlong, 1); | |
| + int lo = xword(q1->val.vlong, 0); | |
| + | |
| + push_addrof(fp, z, POINTER, &zz); | |
| + fprintf(fp, "\t@call_vn __long_loadconst "); | |
| + emit_zop(fp, &zz); | |
| + fprintf(fp, " 0%+ld 0%+ld;\n", (short)hi, (short)lo); | |
| + return; | |
| + } | |
| + | |
| + push_addrof(fp, z, POINTER, &zz); | |
| + push_addrof(fp, q1, POINTER, &q1z); | |
| + fprintf(fp, "\t@copy_table "); | |
| + emit_zop(fp, &q1z); | |
| + fprintf(fp, " "); | |
| + emit_zop(fp, &zz); | |
| + fprintf(fp, " 4;\n"); | |
| +} | |
| + | |
| +/* The code generator itself. | |
| + * This big, complicated, hairy and scary function does the work to actually | |
| + * produce the code. fp is the output stream, ic the beginning of the ic | |
| + * chain, func is a pointer to the actual function and stackframe is the size | |
| + * of the function's stack frame. | |
| + */ | |
| + | |
| +void gen_code(FILE* fp, struct IC *ic, struct Var* func, zlong stackframe) | |
| +{ | |
| + int i; | |
| + struct zop q1; | |
| + struct zop q2; | |
| + struct zop z; | |
| + int code, typf; // ...of the IC under consideration | |
| + | |
| + int c,t,lastcomp=0,reg; | |
| + | |
| + function = func; | |
| + | |
| + /* r0..r5 are always used for parameter passing. */ | |
| + | |
| + regused[2] = 1; | |
| + regused[3] = 1; | |
| + regused[4] = 1; | |
| + regused[5] = 1; | |
| + regused[6] = 1; | |
| + regused[7] = 1; | |
| + | |
| + /* This is the offset of the stack frame, relative to the current stack | |
| + * pointer. */ | |
| + | |
| + stackoffset = stackframe; | |
| + | |
| + /* No parameters pushed yet. */ | |
| + | |
| + stackparamadjust = 0; | |
| + | |
| + reflower(fp); | |
| + | |
| + if (func->storage_class == STATIC) | |
| + fprintf(fp, "[ STATIC_%s_%ld xp\n", modulename, func->offset); | |
| + else | |
| + fprintf(fp, "[ _%s xp\n", func->identifier); | |
| + | |
| + /* Tell Inform what registers the function is using. */ | |
| + | |
| + for (i=1; i<=MAXR; i++) | |
| + { | |
| + //fprintf(fp, "! i=%d used %d scratch %d alloc %d\n", | |
| + // i, regused[i], regscratch[i], regsa[i]); | |
| + if (regused[i] && !regsa[i]) | |
| + fprintf(fp, "\t%s\n", regnames[i]); | |
| + } | |
| + fprintf(fp, ";\n"); | |
| + | |
| + /* Trace the function name. */ | |
| + | |
| + if (g_flags[1] & USEDFLAG) | |
| + { | |
| + if (func->storage_class == STATIC) | |
| + fprintf(fp, "print \"STATIC_%s_%ld^\";\n", modulename, func->offset); | |
| + else | |
| + fprintf(fp, "print \"_%s^\";\n", func->identifier); | |
| + } | |
| + | |
| + /* Adjust stack for locals. */ | |
| + | |
| + if (stackframe) | |
| + fprintf(fp, "\t@sub xp 0%+ld -> xp;\n", stackframe); | |
| + //if (stackoffset) | |
| + // fprintf(fp, "\txp = xp - %ld\n", stackframe); | |
| + | |
| + | |
| + /* Iterate through all ICs. */ | |
| + | |
| + for (; dump_ic(fp, ic), ic; ic=ic->next) | |
| + { | |
| + c=ic->code;t=ic->typf; | |
| + code = ic->code; | |
| + typf = ic->typf; | |
| + | |
| + /* Do nothing for NOPs. */ | |
| + | |
| + if (code == NOP) | |
| + continue; | |
| + | |
| + /* Has the stack been adjusted due to a call? */ | |
| + | |
| +#if 0 | |
| + if (stackcalladjustment) | |
| + { | |
| + if ((code != GETRETURN) && | |
| + (code != FREEREG) && | |
| + (code != ALLOCREG)) | |
| + { | |
| + debugemit(fp, "! stack reset %d %d\n", | |
| + stackparamadjust, stackcallparamsize); | |
| + fprintf(fp, "\t@add xp %d -> xp;\n", | |
| + stackparamadjust+stackcallparamsize); | |
| + stackparamadjust = 0; | |
| + stackcallparamsize = 0; | |
| + stackcalladjustment = 0; | |
| + } | |
| + } | |
| +#endif | |
| + | |
| +#if 0 | |
| + if(notpopped&&!dontpop){ | |
| + int flag=0; | |
| + if(c==LABEL||c==COMPARE||c==TEST||c==BRA){ | |
| + fprintf(fp,"\tadd\t%s,#%ld\n",regnames[sp],notpopped); | |
| + stackoffset+=notpopped;notpopped=0; | |
| + } | |
| + } | |
| +#endif | |
| + /* These opcodes turn into other opcodes. */ | |
| + | |
| + switch (code) | |
| + { | |
| + case SUBPFP: | |
| + case SUBIFP: | |
| + code = SUB; | |
| + break; | |
| + | |
| + case ADDI2P: | |
| + code = ADD; | |
| + break; | |
| + } | |
| + | |
| + /* And now the big opcode switch. */ | |
| + | |
| + switch (code) | |
| + { | |
| + case ALLOCREG: /* Mark register in use */ | |
| + regs[ic->q1.reg] = 1; | |
| + continue; | |
| + | |
| + case FREEREG: /* Mark register not in use */ | |
| + regs[ic->q1.reg] = 0; | |
| + continue; | |
| + | |
| + case LABEL: /* Emit jump target */ | |
| + fprintf(fp, ".%s%d;\n", | |
| + labelprefix, typf); | |
| + continue; | |
| + | |
| + case BRA: /* Unconditional jump */ | |
| + fprintf(fp, "\tjump %s%d;\n", | |
| + labelprefix, typf); | |
| + continue; | |
| + | |
| + case GETRETURN: /* Read the last function call's return parameter */ | |
| + switch (typf & NQ) | |
| + { | |
| + case CHAR: | |
| + //if (ic->q2.val.vlong != 1) | |
| + // goto copy_struct; | |
| + /* fall through */ | |
| + case SHORT: | |
| + case INT: | |
| + case POINTER: | |
| + write_reg(fp, &ic->z, typf, 2); | |
| + break; | |
| + | |
| + /* Ignore the following; the | |
| + * front-end will automatically | |
| + * pass in an implicit | |
| + * parameter to the function | |
| + * containing the address of | |
| + * the return parameter, so | |
| + * GETRETURN ought to be a | |
| + * noop. */ | |
| + case LONG: | |
| + case STRUCT: | |
| + case VOID: | |
| + case ARRAY: | |
| + break; | |
| +#if 0 | |
| + copy_struct: | |
| + push_addrof(fp, &ic->z, typf, &z); | |
| + fprintf(fp, "\t@copy_table xp "); | |
| + emit_zop(fp, &z); | |
| + fprintf(fp, " %ld;\n", szof(ic->z.v->vtyp)); | |
| + break; | |
| +#endif | |
| + | |
| + default: | |
| + ierror(typf & NQ); | |
| + } | |
| + //fprintf(fp, "\tr0 = "); | |
| + //emit_object(fp, &ic->q1, typf); | |
| + //fprintf(fp, ";\n"); | |
| + //write_reg(fp, &ic->z, typf, 2); | |
| + continue; | |
| + | |
| + case SETRETURN: /* Set this function's return parameter */ | |
| + switch (typf & NQ) | |
| + { | |
| + case CHAR: | |
| + //if (ic->q2.val.vlong != 1) | |
| + // goto setreturn_copy_struct; | |
| + /* fall through */ | |
| + case SHORT: | |
| + case INT: | |
| + case POINTER: | |
| + read_reg(fp, &ic->q1, typf, 2); | |
| + break; | |
| + | |
| + case LONG: | |
| + case STRUCT: | |
| + case VOID: | |
| + case ARRAY: | |
| +#if 0 | |
| + setreturn_copy_struct: | |
| + fprintf(fp, "\t@add xp %ld -> sp;\n", | |
| + stackoffset); | |
| + push_addrof(fp, &ic->q1, typf, &q1); | |
| + fprintf(fp, "\t@copy_table "); | |
| + emit_zop(fp, &q1); | |
| + fprintf(fp, " sp %ld;\n", szof(ic->q1.v->vtyp)); | |
| + break; | |
| +#endif | |
| + | |
| + default: | |
| + ierror(typf & NQ); | |
| + } | |
| + //fprintf(fp, "\tr0 = "); | |
| + //emit_object(fp, &ic->q1, typf); | |
| + //fprintf(fp, ";\n"); | |
| + continue; | |
| + | |
| + case MINUS: /* Unary minus */ | |
| + switch (typf & NQ) | |
| + { | |
| + case CHAR: | |
| + case SHORT: | |
| + case INT: | |
| + push_value(fp, &ic->q1, typf, &q1); | |
| + pop_value(fp, &ic->z, typf, &z); | |
| + fprintf(fp, "\t@sub 0 "); | |
| + emit_zop(fp, &q1); | |
| + fprintf(fp, " -> "); | |
| + emit_zop(fp, &z); | |
| + fprintf(fp, ";\n"); | |
| + fin_zop(fp, &ic->z, typf, &z); | |
| + break; | |
| + | |
| + case LONG: | |
| + push_addrof(fp, &ic->z, typf, &z); | |
| + push_addrof(fp, &ic->q1, typf, &q1); | |
| + fprintf(fp, "\t@call_vn __long_neg "); | |
| + emit_zop(fp, &q1); | |
| + fprintf(fp, " "); | |
| + emit_zop(fp, &z); | |
| + fprintf(fp, ";\n"); | |
| + break; | |
| + | |
| + default: | |
| + ierror(0); | |
| + } | |
| + continue; | |
| + | |
| + case KOMPLEMENT: /* Unary komplement */ | |
| + /* INFORM BUG! */ | |
| + /* The @not opcode doesn't work. We have to use a | |
| + * wrapper function instead. */ | |
| + | |
| + push_value(fp, &ic->q1, typf, &q1); | |
| + pop_value(fp, &ic->z, typf, &z); | |
| + fprintf(fp, "\t@call_2s __not "); | |
| + emit_zop(fp, &q1); | |
| + fprintf(fp, " -> "); | |
| + emit_zop(fp, &z); | |
| + fprintf(fp, ";\n"); | |
| + fin_zop(fp, &ic->z, typf, &z); | |
| + continue; | |
| + | |
| + case MOVEFROMREG: /* Write a register to memory */ | |
| + write_reg(fp, &ic->z, typf, ic->q1.reg); | |
| + continue; | |
| + | |
| + case MOVETOREG: /* Read a register from memory */ | |
| + read_reg(fp, &ic->q1, typf, ic->z.reg); | |
| + continue; | |
| + | |
| + case ASSIGN: /* Move something to somewhere else */ | |
| + debugemit(fp, "! ASSIGN size %d typf %d\n", ic->q2.val.vlong, typf & NQ); | |
| + switch (typf & NQ) | |
| + { | |
| + case CHAR: | |
| + if (ic->q2.val.vlong != 1) | |
| + goto assign_copy_struct; | |
| + /* fall through */ | |
| + case SHORT: | |
| + case INT: | |
| + case POINTER: | |
| + move_value(fp, &ic->q1, &ic->z, typf); | |
| + break; | |
| + | |
| + case LONG: | |
| + move_long_value(fp, &ic->q1, &ic->z, typf); | |
| + break; | |
| + | |
| + case STRUCT: | |
| + case VOID: | |
| + case ARRAY: | |
| + assign_copy_struct: | |
| + push_addrof(fp, &ic->z, typf, &z); | |
| + push_addrof(fp, &ic->q1, typf, &q1); | |
| + fprintf(fp, "\t@copy_table "); | |
| + emit_zop(fp, &q1); | |
| + fprintf(fp, " "); | |
| + emit_zop(fp, &z); | |
| + fprintf(fp, " 0%+ld;\n", ic->q2.val.vlong); | |
| + break; | |
| + | |
| + default: | |
| + ierror(typf & NQ); | |
| + } | |
| + continue; | |
| + | |
| + case ADDRESS: /* Fetch the address of something, always | |
| + AUTO or STATIC */ | |
| + i = voff(&ic->q1); | |
| + pop_value(fp, &ic->z, typf, &z); | |
| + fprintf(fp, "\t@add xp 0%+ld -> ", i); | |
| + emit_zop(fp, &z); | |
| + fprintf(fp, ";\n"); | |
| + fin_zop(fp, &ic->z, typf, &z); | |
| + continue; | |
| + | |
| + case PUSH: /* Push a value onto the stack */ | |
| + fprintf(fp, "\t@sub xp 0%+ld -> xp;\n", | |
| + ic->q2.val.vlong); | |
| + //stackoffset += ic->q2.val.vlong; | |
| + stackparamadjust += ic->q2.val.vlong; | |
| + | |
| + switch (ic->q2.val.vlong) | |
| + { | |
| + case 1: | |
| + push_value(fp, &ic->q1, typf, &q1); | |
| + fprintf(fp, "\t@storeb xp 0 "); | |
| + emit_zop(fp, &q1); | |
| + fprintf(fp, ";\n"); | |
| + break; | |
| + | |
| + case 2: | |
| + push_value(fp, &ic->q1, typf, &q1); | |
| + fprintf(fp, "\t@storew xp 0 "); | |
| + emit_zop(fp, &q1); | |
| + fprintf(fp, ";\n"); | |
| + break; | |
| + | |
| + default: | |
| + push_addrof(fp, &ic->q1, typf, &q1); | |
| + fprintf(fp, "\t@copy_table "); | |
| + emit_zop(fp, &q1); | |
| + fprintf(fp, " xp 0%+ld;\n", ic->q2.val.vlong); | |
| + break; | |
| + } | |
| + continue; | |
| + | |
| + case ADD: /* Add two numbers */ | |
| + case SUB: /* Subtract two numbers */ | |
| + case MULT: /* Multiply two numbers */ | |
| + case DIV: /* Divide two numbers */ | |
| + case MOD: /* Modulo two numbers */ | |
| + case OR: /* Bitwise or */ | |
| + case XOR: /* Bitwise xor */ | |
| + case AND: /* Bitwise and */ | |
| + case LSHIFT: /* Shift left */ | |
| + case RSHIFT: /* Shift right */ | |
| + switch (typf & NQ) | |
| + { | |
| + case CHAR: | |
| + case SHORT: | |
| + case INT: | |
| + case POINTER: | |
| + /* Second parameter first! */ | |
| + push_value(fp, &ic->q2, typf, &q2); | |
| + | |
| + if (code == RSHIFT) | |
| + { | |
| + fprintf(fp, "\t@sub 0 "); | |
| + emit_zop(fp, &q2); | |
| + fprintf(fp, " -> sp;\n"); | |
| + q2.type = ZOP_STACK; | |
| + } | |
| + | |
| + push_value(fp, &ic->q1, typf, &q1); | |
| + pop_value(fp, &ic->z, typf, &z); | |
| + //fprintf(fp, "\t"); | |
| + //emit_object(fp, &ic->z, typf); | |
| + //fprintf(fp, " = "); | |
| + //emit_object(fp, &ic->q1, typf); | |
| + switch (code) | |
| + { | |
| + case ADD: | |
| + fprintf(fp, "\t@add "); | |
| + break; | |
| + | |
| + case SUB: | |
| + fprintf(fp, "\t@sub "); | |
| + break; | |
| + | |
| + case MULT: | |
| + fprintf(fp, "\t@mul "); | |
| + break; | |
| + | |
| + case DIV: | |
| + if (typf & UNSIGNED) | |
| + fprintf(fp, "\t@call_vs __unsigned_div "); | |
| + else | |
| + fprintf(fp, "\t@div "); | |
| + break; | |
| + | |
| + case MOD: | |
| + if (typf & UNSIGNED) | |
| + fprintf(fp, "\t@call_vs __unsigned_mod "); | |
| + else | |
| + fprintf(fp, "\t@mod "); | |
| + break; | |
| + | |
| + case AND: | |
| + fprintf(fp, "\t@and "); | |
| + break; | |
| + | |
| + case XOR: | |
| + fprintf(fp, "\t@call_vs __xor "); | |
| + break; | |
| + | |
| + case OR: | |
| + fprintf(fp, "\t@or "); | |
| + break; | |
| + | |
| + case LSHIFT: | |
| + case RSHIFT: | |
| + if (typf & UNSIGNED) | |
| + fprintf(fp, "\t@log_shift "); | |
| + else | |
| + fprintf(fp, "\t@art_shift "); | |
| + break; | |
| + | |
| + default: | |
| + /* Should never get here! */ | |
| + ierror(0); | |
| + } | |
| + emit_zop(fp, &q1); | |
| + fprintf(fp, " "); | |
| + emit_zop(fp, &q2); | |
| + fprintf(fp, " -> "); | |
| + emit_zop(fp, &z); | |
| + fprintf(fp, ";\n"); | |
| + fin_zop(fp, &ic->z, typf, &z); | |
| + //emit_object(fp, &ic->q2, typf); | |
| + break; | |
| + | |
| + case LONG: | |
| + /* Destination parameter first! */ | |
| + | |
| + push_addrof(fp, &ic->z, typf, &z); | |
| + push_addrof(fp, &ic->q2, typf, &q2); | |
| + push_addrof(fp, &ic->q1, typf, &q1); | |
| + | |
| + fprintf(fp, "\t@call_vn __long_"); | |
| + switch (code) | |
| + { | |
| + case ADD: | |
| + fprintf(fp, "add"); | |
| + break; | |
| + | |
| + case SUB: | |
| + fprintf(fp, "sub"); | |
| + break; | |
| + | |
| + case MULT: | |
| + fprintf(fp, "mul"); | |
| + break; | |
| + | |
| + case DIV: | |
| + if (typf & UNSIGNED) | |
| + fprintf(fp, "unsigned_div"); | |
| + else | |
| + fprintf(fp, "div"); | |
| + break; | |
| + | |
| + case MOD: | |
| + if (typf & UNSIGNED) | |
| + fprintf(fp, "unsigned_mod"); | |
| + else | |
| + fprintf(fp, "mod"); | |
| + break; | |
| + | |
| + case AND: | |
| + fprintf(fp, "and"); | |
| + break; | |
| + | |
| + case XOR: | |
| + fprintf(fp, "xor"); | |
| + break; | |
| + | |
| + case OR: | |
| + fprintf(fp, "or"); | |
| + break; | |
| + | |
| + case LSHIFT: | |
| + fprintf(fp, "lsl"); | |
| + break; | |
| + | |
| + case RSHIFT: | |
| + if (typf & UNSIGNED) | |
| + fprintf(fp, "lsr"); | |
| + else | |
| + fprintf(fp, "asr"); | |
| + break; | |
| + | |
| + default: | |
| + /* Should never get here! */ | |
| + ierror(0); | |
| + } | |
| + fprintf(fp, " "); | |
| + emit_zop(fp, &q1); | |
| + fprintf(fp, " "); | |
| + emit_zop(fp, &q2); | |
| + fprintf(fp, " "); | |
| + emit_zop(fp, &z); | |
| + fprintf(fp, ";\n"); | |
| + break; | |
| + | |
| + default: | |
| + ierror(0); | |
| + } | |
| + continue; | |
| + | |
| + case CONVCHAR: /* Convert from char */ | |
| + switch (typf & NU) | |
| + { | |
| + case CHAR: | |
| + case UNSIGNED|CHAR: | |
| + case UNSIGNED|SHORT: | |
| + case UNSIGNED|INT: | |
| + case SHORT: | |
| + case INT: | |
| + push_value(fp, &ic->q1, CHAR, &q1); | |
| + pop_value(fp, &ic->z, typf, &z); | |
| + fprintf(fp, "\t@log_shift "); | |
| + emit_zop(fp, &q1); | |
| + fprintf(fp, " 8 -> sp;\n"); | |
| + fprintf(fp, "\t@art_shift sp 0-8 -> "); | |
| + emit_zop(fp, &z); | |
| + fprintf(fp, ";\n"); | |
| + fin_zop(fp, &ic->z, typf, &z); | |
| + break; | |
| + | |
| + case LONG: | |
| + push_value(fp, &ic->q1, INT, &q1); | |
| + push_addrof(fp, &ic->z, typf, &z); | |
| + fprintf(fp, "\t@call_vn __long_fromchar"); | |
| + emit_zop(fp, &z); | |
| + fprintf(fp, " "); | |
| + emit_zop(fp, &q1); | |
| + fprintf(fp, ";\n"); | |
| + break; | |
| + | |
| + default: | |
| + ierror(0); | |
| + } | |
| + continue; | |
| + | |
| + case CONVUCHAR: /* Convert from unsigned char */ | |
| + switch (typf & NQ) | |
| + { | |
| + case CHAR: | |
| + case SHORT: | |
| + case INT: | |
| + push_value(fp, &ic->q1, UNSIGNED|CHAR, &q1); | |
| + pop_value(fp, &ic->z, typf, &z); | |
| + if ((z.type != ZOP_STACK) || (q1.type != ZOP_STACK)) | |
| + { | |
| + emit_add(fp, &q1, &zop_zero, &z); | |
| +#if 0 | |
| + fprintf(fp, "\t@add "); | |
| + emit_zop(fp, &q1); | |
| + fprintf(fp, " 0 -> "); | |
| + emit_zop(fp, &z); | |
| + fprintf(fp, ";\n"); | |
| +#endif | |
| + } | |
| + fin_zop(fp, &ic->z, typf, &z); | |
| + break; | |
| + | |
| + case LONG: | |
| + push_value(fp, &ic->q1, UNSIGNED|CHAR, &q1); | |
| + push_addrof(fp, &ic->z, typf, &z); | |
| + fprintf(fp, "\t@call_vn __long_fromint"); | |
| + emit_zop(fp, &z); | |
| + fprintf(fp, " 0 "); | |
| + emit_zop(fp, &q1); | |
| + fprintf(fp, ";\n"); | |
| + break; | |
| + | |
| + default: | |
| + ierror(0); | |
| + } | |
| + continue; | |
| + | |
| + case CONVSHORT: /* Convert from short */ | |
| + case CONVINT: /* Convert from int */ | |
| + switch (typf & NU) | |
| + { | |
| + case CHAR: | |
| + case UNSIGNED|CHAR: | |
| + case UNSIGNED|SHORT: | |
| + case UNSIGNED|INT: | |
| + case SHORT: | |
| + case INT: | |
| + push_value(fp, &ic->q1, INT, &q1); | |
| + pop_value(fp, &ic->z, typf, &z); | |
| + if ((z.type != ZOP_STACK) || (q1.type != ZOP_STACK)) | |
| + { | |
| + emit_add(fp, &q1, &zop_zero, &z); | |
| +#if 0 | |
| + fprintf(fp, "\t@add "); | |
| + emit_zop(fp, &q1); | |
| + fprintf(fp, " 0 -> "); | |
| + emit_zop(fp, &z); | |
| + fprintf(fp, ";\n"); | |
| +#endif | |
| + } | |
| + fin_zop(fp, &ic->z, typf, &z); | |
| + break; | |
| + | |
| + case LONG: | |
| + push_value(fp, &ic->q1, INT, &q1); | |
| + push_addrof(fp, &ic->z, typf, &z); | |
| + fprintf(fp, "\t@call_vn __long_fromint "); | |
| + emit_zop(fp, &z); | |
| + fprintf(fp, " "); | |
| + emit_zop(fp, &q1); | |
| + fprintf(fp, ";\n"); | |
| + break; | |
| + | |
| + case UNSIGNED|LONG: | |
| + push_value(fp, &ic->q1, INT, &q1); | |
| + push_addrof(fp, &ic->z, typf, &z); | |
| + fprintf(fp, "\t@call_vn __long_loadconst "); | |
| + emit_zop(fp, &z); | |
| + fprintf(fp, " 0 "); | |
| + emit_zop(fp, &q1); | |
| + fprintf(fp, ";\n"); | |
| + break; | |
| + | |
| + default: | |
| + ierror(typf); | |
| + } | |
| + continue; | |
| + | |
| + case CONVUSHORT: /* Convert from unsigned short */ | |
| + case CONVUINT: /* Convert from unsigned int */ | |
| + case CONVPOINTER: /* Convert from pointer */ | |
| + switch (typf & NQ) | |
| + { | |
| + case CHAR: | |
| + case SHORT: | |
| + case INT: | |
| + push_value(fp, &ic->q1, INT, &q1); | |
| + pop_value(fp, &ic->z, typf, &z); | |
| + if ((z.type != ZOP_STACK) || (q1.type != ZOP_STACK)) | |
| + { | |
| + emit_add(fp, &q1, &zop_zero, &z); | |
| +#if 0 | |
| + fprintf(fp, "\t@add "); | |
| + emit_zop(fp, &q1); | |
| + fprintf(fp, " 0 -> "); | |
| + emit_zop(fp, &z); | |
| + fprintf(fp, ";\n"); | |
| +#endif | |
| + } | |
| + fin_zop(fp, &ic->z, typf, &z); | |
| + break; | |
| + | |
| + case LONG: | |
| + push_value(fp, &ic->q1, INT, &q1); | |
| + push_addrof(fp, &ic->z, typf, &z); | |
| + fprintf(fp, "\t@call_vn __long_loadconst "); | |
| + emit_zop(fp, &z); | |
| + fprintf(fp, " 0 "); | |
| + emit_zop(fp, &q1); | |
| + fprintf(fp, ";\n"); | |
| + break; | |
| +#if 0 | |
| + case SHORT: | |
| + case INT: | |
| + fprintf(fp, "\t"); | |
| + emit_object(fp, &ic->z, typf); | |
| + fprintf(fp, " = ("); | |
| + emit_object(fp, &ic->q1, CHAR); | |
| + fprintf(fp, ") << 8 >> 8;\n"); | |
| + break; | |
| +#endif | |
| + | |
| + default: | |
| + printf("%X\n", typf); | |
| + ierror(0); | |
| + } | |
| + continue; | |
| + | |
| + case CONVULONG: /* Convert from unsigned long */ | |
| + case CONVLONG: /* Convert from long */ | |
| + switch (typf & NQ) | |
| + { | |
| + case CHAR: | |
| + push_addrof(fp, &ic->q1, LONG, &q1); | |
| + pop_value(fp, &ic->z, typf, &z); | |
| + fprintf(fp, "\t@loadb "); | |
| + emit_zop(fp, &q1); | |
| + fprintf(fp, " 3 -> "); | |
| + emit_zop(fp, &z); | |
| + fprintf(fp, ";\n"); | |
| + fin_zop(fp, &ic->z, typf, &z); | |
| + break; | |
| + | |
| + case SHORT: | |
| + case INT: | |
| + push_addrof(fp, &ic->q1, LONG, &q1); | |
| + pop_value(fp, &ic->z, typf, &z); | |
| + fprintf(fp, "\t@loadw "); | |
| + emit_zop(fp, &q1); | |
| + fprintf(fp, " 1 -> "); | |
| + emit_zop(fp, &z); | |
| + fprintf(fp, ";\n"); | |
| + fin_zop(fp, &ic->z, typf, &z); | |
| + break; | |
| + | |
| + default: | |
| + ierror(typf & NQ); | |
| + } | |
| + continue; | |
| + | |
| + case COMPARE: | |
| + /* COMPARE is special. The next instruction is | |
| + * always a branch. The Z-machine does | |
| + * branches in the form: | |
| + * | |
| + * @j{e,g,l} <var1> <var2> [~]@<label> | |
| + * | |
| + * However, we don't know what short of branch | |
| + * to emit until the next instruction (which is | |
| + * the IC for a branch). So we have to stash | |
| + * the zops that we're using for the | |
| + * compare here, for use later. This is done | |
| + * using the globals compare1 and compare2. | |
| + */ | |
| + | |
| + switch (typf & NU) | |
| + { | |
| + case CHAR: | |
| + case SHORT: | |
| + case INT: | |
| + case POINTER: | |
| + /* Second parameter first! */ | |
| + push_value(fp, &ic->q2, typf, &compare2); | |
| + push_value(fp, &ic->q1, typf, &compare1); | |
| + break; | |
| + | |
| + case UNSIGNED|CHAR: | |
| + case UNSIGNED|SHORT: | |
| + case UNSIGNED|INT: | |
| + /* Because the Z-machine only | |
| + * has signed comparisons, we | |
| + * need a dodgy algorithm to | |
| + * do this, which works as | |
| + * follows: in the signed | |
| + * domain, 0-7FFF compares | |
| + * greater than 8000-FFFF. In | |
| + * the unsigned domain, it's | |
| + * the other way around. So, | |
| + * by flipping the sign bits | |
| + * we do the logical | |
| + * equivalent of shifting the | |
| + * unsigned range up/down by | |
| + * 8000 which makes it fit | |
| + * the signed range. There. | |
| + * Did you understand that? | |
| + * Neither did I, the first | |
| + * few times it was explained | |
| + * to me. */ | |
| + read_reg(fp, &ic->q2, typf, 0); | |
| + fprintf(fp, "\t@add sp $8000 -> sp;\n"); | |
| + read_reg(fp, &ic->q1, typf, 0); | |
| + fprintf(fp, "\t@add sp $8000 -> sp;\n"); | |
| + compare1.type = ZOP_STACK; | |
| + compare2.type = ZOP_STACK; | |
| + break; | |
| + | |
| + case LONG: | |
| + push_addrof(fp, &ic->q2, typf, &q2); | |
| + push_addrof(fp, &ic->q1, typf, &q1); | |
| + fprintf(fp, "\t@call_vs __long_compare "); | |
| + emit_zop(fp, &q1); | |
| + fprintf(fp, " "); | |
| + emit_zop(fp, &q2); | |
| + fprintf(fp, " -> sp;\n"); | |
| + compare1.type = ZOP_STACK; | |
| + compare2.type = ZOP_CONSTANT; | |
| + compare2.val.constant = 0; | |
| + break; | |
| + | |
| + case UNSIGNED|LONG: | |
| + push_addrof(fp, &ic->q2, typf, &q2); | |
| + push_addrof(fp, &ic->q1, typf, &q1); | |
| + fprintf(fp, "\t@call_vs __long_unsigned_compare "); | |
| + emit_zop(fp, &q1); | |
| + fprintf(fp, " "); | |
| + emit_zop(fp, &q2); | |
| + fprintf(fp, " -> sp;\n"); | |
| + compare1.type = ZOP_STACK; | |
| + compare2.type = ZOP_CONSTANT; | |
| + compare2.val.constant = 0; | |
| + break; | |
| + | |
| + default: | |
| + ierror(typf & NQ); | |
| + } | |
| + continue; | |
| + | |
| + case TEST: | |
| + /* TEST is a special COMPARE. It takes one | |
| + * parameter and always tests it against 0; it | |
| + * is guaranteed to be followed by BNE or BEQ. | |
| + * */ | |
| + | |
| + switch (typf & NQ) | |
| + { | |
| + case CHAR: | |
| + case SHORT: | |
| + case INT: | |
| + case POINTER: | |
| + push_value(fp, &ic->q1, typf, &compare1); | |
| + compare2.type = ZOP_CONSTANT; | |
| + compare2.val.constant = 0; | |
| + break; | |
| + | |
| + case LONG: | |
| + push_addrof(fp, &ic->q1, typf, &q1); | |
| + fprintf(fp, "\t@call_vs __long_compare "); | |
| + emit_zop(fp, &q1); | |
| + fprintf(fp, " "); | |
| + q2.type = ZOP_CONSTANTADDR; | |
| + q2.val.constant = addconstant(0); | |
| + emit_zop(fp, &q2); | |
| + fprintf(fp, " -> sp;\n", i); | |
| + compare1.type = ZOP_STACK; | |
| + compare2.type = ZOP_CONSTANT; | |
| + compare2.val.constant = 0; | |
| + break; | |
| + | |
| + default: | |
| + ierror(typf & NQ); | |
| + } | |
| + continue; | |
| + | |
| + case BEQ: | |
| + case BNE: | |
| + case BLT: | |
| + case BGE: | |
| + case BLE: | |
| + case BGT: | |
| + { | |
| + static int branchlabel = 0; | |
| + | |
| + fprintf(fp, "\t@j"); | |
| + switch (code) | |
| + { | |
| + case BNE: | |
| + case BEQ: fprintf(fp, "e "); break; | |
| + case BLT: | |
| + case BGE: fprintf(fp, "l "); break; | |
| + case BGT: | |
| + case BLE: fprintf(fp, "g "); break; | |
| + } | |
| + | |
| + emit_zop(fp, &compare1); | |
| + fprintf(fp, " "); | |
| + emit_zop(fp, &compare2); | |
| + fprintf(fp, " ?"); | |
| + | |
| + if (g_flags[3] & USEDFLAG) | |
| + { | |
| + if (!((code == BNE) || (code == BGE) || (code == BLE))) | |
| + fprintf(fp, "~"); | |
| + fprintf(fp, "LL%d;\n", branchlabel); | |
| + fprintf(fp, "\tjump %s%d;\n", labelprefix, typf); | |
| + fprintf(fp, ".LL%d;\n", branchlabel++); | |
| + } | |
| + else | |
| + { | |
| + if ((code == BNE) || (code == BGE) || (code == BLE)) | |
| + fprintf(fp, "~"); | |
| + fprintf(fp, "%s%d;\n", labelprefix, typf); | |
| + } | |
| + continue; | |
| + } | |
| + | |
| + case CALL: | |
| + { | |
| +#if 0 | |
| + /* Calculate the amount of stack to reserve for | |
| + * the return parameter. ints and smaller go in | |
| + * the return register. */ | |
| + | |
| + stackcallparamsize = szof(ic->q1.v->vtyp->next); | |
| + if (stackcallparamsize <= sizetab[INT]) | |
| + stackcallparamsize = 0; | |
| + | |
| + if (stackcallparamsize) | |
| + fprintf(fp, "\t@sub xp %d -> xp;\n", | |
| + stackcallparamsize); | |
| +#endif | |
| + | |
| + /* Is this actually an inline assembly function? */ | |
| + | |
| + if ((ic->q1.flags & VAR) && | |
| + ic->q1.v->fi && | |
| + ic->q1.v->fi->inline_asm) | |
| + { | |
| + /* Yes. Emit the assembly code. */ | |
| + | |
| + fprintf(fp, "%s", ic->q1.v->fi->inline_asm); | |
| + } | |
| + else | |
| + { | |
| + /* No; so emit a call. */ | |
| + | |
| + push_value(fp, &ic->q1, typf, &q1); | |
| + fprintf(fp, "\t@call_vs2 "); | |
| + emit_zop(fp, &q1); | |
| + fprintf(fp, " xp r0 r1 r2 r3 r4 r5 -> r0;\n"); | |
| + } | |
| + | |
| + //stackcalladjustment = 1; | |
| + | |
| + /* If any parameters have been pushed, adjust | |
| + * the stack to pop them. */ | |
| + | |
| + if (stackparamadjust) | |
| + { | |
| + fprintf(fp, "\t@add xp 0%+ld -> xp;\n", | |
| + stackparamadjust); | |
| + //stackoffset -= stackparamadjust; | |
| + stackparamadjust = 0; | |
| + } | |
| + continue; | |
| + } | |
| + | |
| + default: | |
| + ierror(code); | |
| + } | |
| + | |
| + } | |
| + | |
| + /* We really ought to tidy the stack up; but there's no need, because | |
| + * the old value of xp will be restored when the function exits. */ | |
| + | |
| + //if (stackframe) | |
| + // fprintf(fp, "\t@add xp %ld -> xp;\n", stackframe); | |
| + | |
| + fprintf(fp, "\t@ret r0;\n"); | |
| + fprintf(fp, "]\n"); | |
| + | |
| +// function_bottom(fp, func, loff); | |
| +} | |
| + | |
| +int shortcut(int code, int typ) | |
| +{ | |
| + return(0); | |
| +} | |
| + | |
| +// Add a constant to the constant pool. | |
| + | |
| +static int addconstant(zlong value) | |
| +{ | |
| + struct constant* c; | |
| + | |
| + /* Check to see if the constant's already in the pool. */ | |
| + | |
| + c = constantlist; | |
| + while (c) | |
| + { | |
| + if (c->value == value) | |
| + return c->id; | |
| + c = c->next; | |
| + } | |
| + | |
| + /* It's not; add it. */ | |
| + | |
| + c = malloc(sizeof(struct constant)); | |
| + c->next = constantlist; | |
| + c->id = constantnum++; | |
| + c->value = value; | |
| + constantlist = c; | |
| + return c->id; | |
| +} | |
| + | |
| +void cleanup_cg(FILE *fp) | |
| +{ | |
| + struct fixup* fixup = fixuplist; | |
| + | |
| + /* Have we actually emitted anything? */ | |
| + | |
| + if (!fp) | |
| + return; | |
| + | |
| + reflower(fp); | |
| + | |
| + /* Emit the constant pool. */ | |
| + | |
| + { | |
| + struct constant* constant = constantlist; | |
| + | |
| + while (constant) | |
| + { | |
| + fprintf(fp, "Array CONSTANT_%s_%ld -->\n", | |
| + modulename, constant->id); | |
| + fprintf(fp, " 0%+ld 0%+ld;\n", | |
| + xword(constant->value, 1), | |
| + xword(constant->value, 0)); | |
| + constant = constant->next; | |
| + } | |
| + } | |
| + | |
| + /* Emit the code to initialise the data area. */ | |
| + | |
| + { | |
| + struct fixup* fixup = fixuplist; | |
| + | |
| + fprintf(fp, "[ __init_vars_%s;\n", modulename); | |
| + while (fixup) | |
| + { | |
| + fprintf(fp, "\t@add 0%+ld ", fixup->offset); | |
| + | |
| + switch (fixup->value.type) | |
| + { | |
| + case STATIC: | |
| + fprintf(fp, "STATIC_%s_%ld -> sp;\n", | |
| + modulename, fixup->value.val.number); | |
| + break; | |
| + | |
| + case EXTERN: | |
| + fprintf(fp, "_%s -> sp;\n", | |
| + fixup->value.val.identifier); | |
| + break; | |
| + | |
| + default: | |
| + ierror(0); | |
| + } | |
| + | |
| + switch (fixup->identifier.type) | |
| + { | |
| + case STATIC: | |
| + fprintf(fp, "\t@storew STATIC_%s_%ld 0%+ld sp;\n", | |
| + modulename, fixup->identifier.val.number, | |
| + fixup->identifier.offset); | |
| + break; | |
| + | |
| + case EXTERN: | |
| + fprintf(fp, "\t@storew _%s 0%+ld sp;\n", | |
| + fixup->identifier.val.identifier, | |
| + fixup->identifier.offset); | |
| + break; | |
| + | |
| + default: | |
| + ierror(0); | |
| + } | |
| + | |
| + fixup = fixup->next; | |
| + } | |
| + fprintf(fp, "];\n"); | |
| + } | |
| +} | |
| + | |
| +/* The code generator's asking us to pass a parameter in a register. */ | |
| + | |
| +int reg_parm(struct reg_handle *rh, struct Typ *typ, int vararg) | |
| +{ | |
| + /* Vararg parameters never go in registers. */ | |
| + | |
| + if (vararg) | |
| + return 0; | |
| + | |
| + /* Will the parameter fit? */ | |
| + | |
| + if (sizetab[typ->flags & NQ] > 2) | |
| + return 0; | |
| + | |
| + /* Still enough registers? */ | |
| + | |
| + if (rh->reg >= NUM_REGPARMS+USERREG) | |
| + return 0; | |
| + | |
| + return (rh->reg++); | |
| +} | |
| + | |
| --- vbcc-0.7.orig/ic.c | |
| +++ vbcc-0.7/ic.c | |
| int do_arith(np,struct IC *,np,struct obj *); | |
| +static void handle_reglist(struct regargs_list *,struct obj *); | |
| + | |
| void gen_test(struct obj *o,int t,int branch,int label) | |
| /* Generiert ein test o, branch label und passt auf, dass */ | |
| /* kein TEST const generiert wird. */ | |
| ptyp.next=p->ntyp; | |
| reg=reg_parm(®_handle,&ptyp,0); | |
| if(!reg) ierror(0); | |
| - sz=push_args(p->alist,p->left->ntyp->next->exact,0,&rl,®_handle,&ret_obj,reg); | |
| + sz=push_args(p->alist,p->left->ntyp->next->exact,0,&rl,®_handle,&ret_obj,p->ntyp,reg); | |
| + if(optflags&2) | |
| + handle_reglist(rl,&ret_obj); | |
| }else{ | |
| - sz=push_args(p->alist,p->left->ntyp->next->exact,0,&rl,®_handle,0,-1); | |
| + struct reg_handle reg_handle=empty_reg_handle; | |
| + sz=push_args(p->alist,p->left->ntyp->next->exact,0,&rl,®_handle,0,0,-1); | |
| + if(optflags&2) | |
| + handle_reglist(rl,0); | |
| } | |
| } | |
| #else | |
| sz=push_args(p->alist,p->left->ntyp->next->exact,0,&rl); | |
| + if(optflags&2) | |
| + handle_reglist(rl,0); | |
| #endif | |
| if(!r) gen_IC(p->left,0,0); | |
| if(!(p->left->o.flags&DREFOBJ)){ | |
| free(new); | |
| p->o.flags=0; | |
| } | |
| + | |
| +static void handle_reglist(struct regargs_list *nrl,struct obj *radr) | |
| +{ | |
| + struct IC *new; | |
| + /* Letztes Argument; jetzt in Register laden. */ | |
| +#ifdef HAVE_REGPARMS | |
| + int didradr=0; | |
| +#endif | |
| + while(nrl){ | |
| + new=mymalloc(ICS); | |
| + new->code=ASSIGN; | |
| + new->typf=nrl->v->vtyp->flags|VOLATILE; | |
| + new->q1.flags=VAR; | |
| + new->q1.v=nrl->v; | |
| + new->q1.val.vlong=l2zl(0L); | |
| + new->q2.flags=0; | |
| + new->q2.val.vlong=szof(nrl->v->vtyp); | |
| + new->z.flags=VAR; | |
| + new->z.val.vlong=l2zl(0L); | |
| + new->z.v=add_var(empty,clone_typ(nrl->v->vtyp),AUTO,0); | |
| + new->z.v->reg=nrl->reg; | |
| + nrl->v=new->z.v; | |
| + add_IC(new); | |
| + | |
| #ifdef HAVE_REGPARMS | |
| -zlong push_args(struct argument_list *al,struct struct_declaration *sd,int n,struct regargs_list **rl,struct reg_handle *reg_handle,struct obj *radr,int rreg) | |
| + if(radr&&!didradr){ | |
| + didradr=1; | |
| + }else{ | |
| +#endif | |
| + nrl->al->pushic=new; | |
| +#ifdef HAVE_REGPARMS | |
| + } | |
| +#endif | |
| + nrl=nrl->next; | |
| + } | |
| +} | |
| + | |
| +#ifdef HAVE_REGPARMS | |
| +zlong push_args(struct argument_list *al,struct struct_declaration *sd,int n,struct regargs_list **rl,struct reg_handle *reg_handle,struct obj *radr,struct Typ *rtype,int rreg) | |
| #else | |
| zlong push_args(struct argument_list *al,struct struct_declaration *sd,int n,struct regargs_list **rl) | |
| #endif | |
| /* auf den Stack. Es wird Integer-Erweiterung vorgenommen und float wird */ | |
| /* nach double konvertiert, falls kein Prototype da ist. */ | |
| { | |
| - int t,reg,regpush,evaluated=0; | |
| + int t,reg,regpush,evaluated=0;struct Typ *ft; | |
| struct IC *new;struct regargs_list *nrl;zlong sz,of;struct obj *arg; | |
| #ifdef HAVE_REGPARMS | |
| int stdreg; | |
| if(!al->arg) ierror(0); | |
| if(!sd) ierror(0); | |
| if(n<sd->count){ | |
| - t=(*sd->sl)[n].styp->flags;sz=szof((*sd->sl)[n].styp); | |
| + ft=clone_typ((*sd->sl)[n].styp);sz=szof(ft); | |
| + t=ft->flags; | |
| reg=(*sd->sl)[n].reg; | |
| }else{ | |
| - t=al->arg->ntyp->flags;sz=szof(al->arg->ntyp); | |
| + ft=clone_typ(al->arg->ntyp);sz=szof(ft); | |
| + t=ft->flags; | |
| } | |
| - if((t&NQ)>=CHAR&&(t&NQ)<=LONG) {t=int_erw(t);sz=sizetab[t&NQ];} | |
| + if((t&NQ)>=CHAR&&(t&NQ)<=LONG) {t=int_erw(t);ft->flags=t;sz=sizetab[t&NQ];} | |
| if((t&NQ)==FLOAT&&n>=sd->count) {t=DOUBLE;sz=sizetab[t];} | |
| #ifdef HAVE_REGPARMS | |
| }else{ | |
| - t=POINTER;sz=sizetab[POINTER]; | |
| + ft=mymalloc(TYPS); | |
| + ft->flags=t=POINTER; | |
| + ft->next=clone_typ(rtype); | |
| + sz=sizetab[t]; | |
| } | |
| #endif | |
| if(reg<0) {reg=-reg;regpush=1;} else regpush=0; | |
| convert(al->arg,t&NU); | |
| evaluated=1; | |
| new->q1=al->arg->o; | |
| + al->pushic=new; | |
| }else | |
| new->q1=*radr; | |
| /* Parameteruebergabe ueber Stack. */ | |
| #endif | |
| #ifdef HAVE_REGPARMS | |
| if(radr){ | |
| - if(al) of=push_args(al,sd,0,rl,reg_handle,0,0); else of=l2zl(0L); | |
| + if(al) of=push_args(al,sd,0,rl,reg_handle,0,0,0); else of=l2zl(0L); | |
| }else{ | |
| - if(al->next) of=push_args(al->next,sd,n+1,rl,reg_handle,0,0); else of=l2zl(0L); | |
| + if(al->next) of=push_args(al->next,sd,n+1,rl,reg_handle,0,0,0); else of=l2zl(0L); | |
| } | |
| #else | |
| if(al->next) of=push_args(al->next,sd,n+1,rl); else of=l2zl(0L); | |
| }else{ | |
| if(!evaluated){ | |
| gen_IC(al->arg,0,0); | |
| - convert(al->arg,t&NU); | |
| + convert(al->arg,t); | |
| evaluated=1; | |
| } | |
| arg=&al->arg->o; | |
| new->q2.flags=new->z.flags=0; | |
| new->q2.val.vlong=sz; | |
| add_IC(new); | |
| + al->pushic=new; | |
| if(!regpush) return(zladd(of,sz)); | |
| } | |
| #endif | |
| nrl->next=*rl; | |
| nrl->reg=reg; | |
| nrl->v=v; | |
| + nrl->al=al; | |
| *rl=nrl; | |
| -#ifdef HAVE_REGPARMS | |
| - if(radr||(!radr&&rreg==-1)) | |
| -#else | |
| - if(n==0) | |
| -#endif | |
| - { | |
| - /* Letztes Argument; jetzt in Register laden. */ | |
| - for(;nrl;nrl=nrl->next){ | |
| - new=mymalloc(ICS); | |
| - new->code=ASSIGN; | |
| - new->typf=nrl->v->vtyp->flags|VOLATILE; | |
| - new->q1.flags=VAR; | |
| - new->q1.v=nrl->v; | |
| - new->q1.val.vlong=l2zl(0L); | |
| - new->q2.flags=0; | |
| - new->q2.val.vlong=szof(nrl->v->vtyp); | |
| - new->z.flags=VAR; | |
| - new->z.val.vlong=l2zl(0L); | |
| - new->z.v=add_var(empty,clone_typ(nrl->v->vtyp),AUTO,0); | |
| - new->z.v->reg=nrl->reg; | |
| - nrl->v=new->z.v; | |
| - add_IC(new); | |
| - } | |
| - } | |
| return(of); | |
| }else{ | |
| /* Nicht-optimierende Version. */ | |
| }else regs[reg]|=32; | |
| } | |
| new=mymalloc(ICS); | |
| +#ifdef HAVE_REGPARMS | |
| + if(!radr){ | |
| + al->pushic=new; | |
| + } | |
| +#else | |
| + al->pushic=new; | |
| +#endif | |
| new->code=ASSIGN; | |
| new->typf=t; | |
| new->q1=*arg; | |
| new->q1=p->left->o; | |
| /* kleinere Typen als MINADDI2P erst in diesen wandeln */ | |
| if((new->typf&NQ)<MINADDI2P){convert(p->right,/*UNSIGNED|*/MINADDI2P);new->typf=/*UNSIGNED|*/MINADDI2P;} | |
| +#ifdef MAXADDI2P | |
| + if((new->typf&NQ)>MAXADDI2P){convert(p->right,/*UNSIGNED|*/MAXADDI2P);new->typf=/*UNSIGNED|*/MAXADDI2P;} | |
| +#endif | |
| new->q2=p->right->o; | |
| if(!dest&&(p->left->o.flags&SCRATCH)&®ok(new->q1.reg,POINTER,p->left->ntyp->next->flags&NU)){ | |
| new->z=p->left->o; | |
| --- vbcc-0.7.orig/configure | |
| +++ vbcc-0.7/configure | |
| +#! /bin/sh | |
| + | |
| +# Guess values for system-dependent variables and create Makefiles. | |
| +# Generated automatically using autoconf version 2.13 | |
| +# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. | |
| +# | |
| +# This configure script is free software; the Free Software Foundation | |
| +# gives unlimited permission to copy, distribute and modify it. | |
| + | |
| +# Defaults: | |
| +ac_help= | |
| +ac_default_prefix=/usr/local | |
| +# Any additions from configure.in: | |
| + | |
| +# Initialize some variables set by options. | |
| +# The variables have the same names as the options, with | |
| +# dashes changed to underlines. | |
| +build=NONE | |
| +cache_file=./config.cache | |
| +exec_prefix=NONE | |
| +host=NONE | |
| +no_create= | |
| +nonopt=NONE | |
| +no_recursion= | |
| +prefix=NONE | |
| +program_prefix=NONE | |
| +program_suffix=NONE | |
| +program_transform_name=s,x,x, | |
| +silent= | |
| +site= | |
| +srcdir= | |
| +target=NONE | |
| +verbose= | |
| +x_includes=NONE | |
| +x_libraries=NONE | |
| +bindir='${exec_prefix}/bin' | |
| +sbindir='${exec_prefix}/sbin' | |
| +libexecdir='${exec_prefix}/libexec' | |
| +datadir='${prefix}/share' | |
| +sysconfdir='${prefix}/etc' | |
| +sharedstatedir='${prefix}/com' | |
| +localstatedir='${prefix}/var' | |
| +libdir='${exec_prefix}/lib' | |
| +includedir='${prefix}/include' | |
| +oldincludedir='/usr/include' | |
| +infodir='${prefix}/info' | |
| +mandir='${prefix}/man' | |
| + | |
| +# Initialize some other variables. | |
| +subdirs= | |
| +MFLAGS= MAKEFLAGS= | |
| +SHELL=${CONFIG_SHELL-/bin/sh} | |
| +# Maximum number of lines to put in a shell here document. | |
| +ac_max_here_lines=12 | |
| + | |
| +ac_prev= | |
| +for ac_option | |
| +do | |
| + | |
| + # If the previous option needs an argument, assign it. | |
| + if test -n "$ac_prev"; then | |
| + eval "$ac_prev=\$ac_option" | |
| + ac_prev= | |
| + continue | |
| + fi | |
| + | |
| + case "$ac_option" in | |
| + -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; | |
| + *) ac_optarg= ;; | |
| + esac | |
| + | |
| + # Accept the important Cygnus configure options, so we can diagnose typos. | |
| + | |
| + case "$ac_option" in | |
| + | |
| + -bindir | --bindir | --bindi | --bind | --bin | --bi) | |
| + ac_prev=bindir ;; | |
| + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) | |
| + bindir="$ac_optarg" ;; | |
| + | |
| + -build | --build | --buil | --bui | --bu) | |
| + ac_prev=build ;; | |
| + -build=* | --build=* | --buil=* | --bui=* | --bu=*) | |
| + build="$ac_optarg" ;; | |
| + | |
| + -cache-file | --cache-file | --cache-fil | --cache-fi \ | |
| + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) | |
| + ac_prev=cache_file ;; | |
| + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | |
| + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) | |
| + cache_file="$ac_optarg" ;; | |
| + | |
| + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) | |
| + ac_prev=datadir ;; | |
| + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ | |
| + | --da=*) | |
| + datadir="$ac_optarg" ;; | |
| + | |
| + -disable-* | --disable-*) | |
| + ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` | |
| + # Reject names that are not valid shell variable names. | |
| + if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then | |
| + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } | |
| + fi | |
| + ac_feature=`echo $ac_feature| sed 's/-/_/g'` | |
| + eval "enable_${ac_feature}=no" ;; | |
| + | |
| + -enable-* | --enable-*) | |
| + ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` | |
| + # Reject names that are not valid shell variable names. | |
| + if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then | |
| + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } | |
| + fi | |
| + ac_feature=`echo $ac_feature| sed 's/-/_/g'` | |
| + case "$ac_option" in | |
| + *=*) ;; | |
| + *) ac_optarg=yes ;; | |
| + esac | |
| + eval "enable_${ac_feature}='$ac_optarg'" ;; | |
| + | |
| + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | |
| + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | |
| + | --exec | --exe | --ex) | |
| + ac_prev=exec_prefix ;; | |
| + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | |
| + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | |
| + | --exec=* | --exe=* | --ex=*) | |
| + exec_prefix="$ac_optarg" ;; | |
| + | |
| + -gas | --gas | --ga | --g) | |
| + # Obsolete; use --with-gas. | |
| + with_gas=yes ;; | |
| + | |
| + -help | --help | --hel | --he) | |
| + # Omit some internal or obsolete options to make the list less imposing. | |
| + # This message is too long to be a string in the A/UX 3.1 sh. | |
| + cat << EOF | |
| +Usage: configure [options] [host] | |
| +Options: [defaults in brackets after descriptions] | |
| +Configuration: | |
| + --cache-file=FILE cache test results in FILE | |
| + --help print this message | |
| + --no-create do not create output files | |
| + --quiet, --silent do not print \`checking...' messages | |
| + --version print the version of autoconf that created configure | |
| +Directory and file names: | |
| + --prefix=PREFIX install architecture-independent files in PREFIX | |
| + [$ac_default_prefix] | |
| + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX | |
| + [same as prefix] | |
| + --bindir=DIR user executables in DIR [EPREFIX/bin] | |
| + --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] | |
| + --libexecdir=DIR program executables in DIR [EPREFIX/libexec] | |
| + --datadir=DIR read-only architecture-independent data in DIR | |
| + [PREFIX/share] | |
| + --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] | |
| + --sharedstatedir=DIR modifiable architecture-independent data in DIR | |
| + [PREFIX/com] | |
| + --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] | |
| + --libdir=DIR object code libraries in DIR [EPREFIX/lib] | |
| + --includedir=DIR C header files in DIR [PREFIX/include] | |
| + --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] | |
| + --infodir=DIR info documentation in DIR [PREFIX/info] | |
| + --mandir=DIR man documentation in DIR [PREFIX/man] | |
| + --srcdir=DIR find the sources in DIR [configure dir or ..] | |
| + --program-prefix=PREFIX prepend PREFIX to installed program names | |
| + --program-suffix=SUFFIX append SUFFIX to installed program names | |
| + --program-transform-name=PROGRAM | |
| + run sed PROGRAM on installed program names | |
| +EOF | |
| + cat << EOF | |
| +Host type: | |
| + --build=BUILD configure for building on BUILD [BUILD=HOST] | |
| + --host=HOST configure for HOST [guessed] | |
| + --target=TARGET configure for TARGET [TARGET=HOST] | |
| +Features and packages: | |
| + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) | |
| + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] | |
| + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] | |
| + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) | |
| + --x-includes=DIR X include files are in DIR | |
| + --x-libraries=DIR X library files are in DIR | |
| +EOF | |
| + if test -n "$ac_help"; then | |
| + echo "--enable and --with options recognized:$ac_help" | |
| + fi | |
| + exit 0 ;; | |
| + | |
| + -host | --host | --hos | --ho) | |
| + ac_prev=host ;; | |
| + -host=* | --host=* | --hos=* | --ho=*) | |
| + host="$ac_optarg" ;; | |
| + | |
| + -includedir | --includedir | --includedi | --included | --include \ | |
| + | --includ | --inclu | --incl | --inc) | |
| + ac_prev=includedir ;; | |
| + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | |
| + | --includ=* | --inclu=* | --incl=* | --inc=*) | |
| + includedir="$ac_optarg" ;; | |
| + | |
| + -infodir | --infodir | --infodi | --infod | --info | --inf) | |
| + ac_prev=infodir ;; | |
| + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) | |
| + infodir="$ac_optarg" ;; | |
| + | |
| + -libdir | --libdir | --libdi | --libd) | |
| + ac_prev=libdir ;; | |
| + -libdir=* | --libdir=* | --libdi=* | --libd=*) | |
| + libdir="$ac_optarg" ;; | |
| + | |
| + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | |
| + | --libexe | --libex | --libe) | |
| + ac_prev=libexecdir ;; | |
| + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | |
| + | --libexe=* | --libex=* | --libe=*) | |
| + libexecdir="$ac_optarg" ;; | |
| + | |
| + -localstatedir | --localstatedir | --localstatedi | --localstated \ | |
| + | --localstate | --localstat | --localsta | --localst \ | |
| + | --locals | --local | --loca | --loc | --lo) | |
| + ac_prev=localstatedir ;; | |
| + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | |
| + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ | |
| + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) | |
| + localstatedir="$ac_optarg" ;; | |
| + | |
| + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) | |
| + ac_prev=mandir ;; | |
| + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) | |
| + mandir="$ac_optarg" ;; | |
| + | |
| + -nfp | --nfp | --nf) | |
| + # Obsolete; use --without-fp. | |
| + with_fp=no ;; | |
| + | |
| + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | |
| + | --no-cr | --no-c) | |
| + no_create=yes ;; | |
| + | |
| + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | |
| + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) | |
| + no_recursion=yes ;; | |
| + | |
| + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | |
| + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | |
| + | --oldin | --oldi | --old | --ol | --o) | |
| + ac_prev=oldincludedir ;; | |
| + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | |
| + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | |
| + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) | |
| + oldincludedir="$ac_optarg" ;; | |
| + | |
| + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) | |
| + ac_prev=prefix ;; | |
| + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) | |
| + prefix="$ac_optarg" ;; | |
| + | |
| + -program-prefix | --program-prefix | --program-prefi | --program-pref \ | |
| + | --program-pre | --program-pr | --program-p) | |
| + ac_prev=program_prefix ;; | |
| + -program-prefix=* | --program-prefix=* | --program-prefi=* \ | |
| + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) | |
| + program_prefix="$ac_optarg" ;; | |
| + | |
| + -program-suffix | --program-suffix | --program-suffi | --program-suff \ | |
| + | --program-suf | --program-su | --program-s) | |
| + ac_prev=program_suffix ;; | |
| + -program-suffix=* | --program-suffix=* | --program-suffi=* \ | |
| + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) | |
| + program_suffix="$ac_optarg" ;; | |
| + | |
| + -program-transform-name | --program-transform-name \ | |
| + | --program-transform-nam | --program-transform-na \ | |
| + | --program-transform-n | --program-transform- \ | |
| + | --program-transform | --program-transfor \ | |
| + | --program-transfo | --program-transf \ | |
| + | --program-trans | --program-tran \ | |
| + | --progr-tra | --program-tr | --program-t) | |
| + ac_prev=program_transform_name ;; | |
| + -program-transform-name=* | --program-transform-name=* \ | |
| + | --program-transform-nam=* | --program-transform-na=* \ | |
| + | --program-transform-n=* | --program-transform-=* \ | |
| + | --program-transform=* | --program-transfor=* \ | |
| + | --program-transfo=* | --program-transf=* \ | |
| + | --program-trans=* | --program-tran=* \ | |
| + | --progr-tra=* | --program-tr=* | --program-t=*) | |
| + program_transform_name="$ac_optarg" ;; | |
| + | |
| + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | |
| + | -silent | --silent | --silen | --sile | --sil) | |
| + silent=yes ;; | |
| + | |
| + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) | |
| + ac_prev=sbindir ;; | |
| + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | |
| + | --sbi=* | --sb=*) | |
| + sbindir="$ac_optarg" ;; | |
| + | |
| + -sharedstatedir | --sharedstatedir | --sharedstatedi \ | |
| + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | |
| + | --sharedst | --shareds | --shared | --share | --shar \ | |
| + | --sha | --sh) | |
| + ac_prev=sharedstatedir ;; | |
| + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | |
| + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | |
| + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | |
| + | --sha=* | --sh=*) | |
| + sharedstatedir="$ac_optarg" ;; | |
| + | |
| + -site | --site | --sit) | |
| + ac_prev=site ;; | |
| + -site=* | --site=* | --sit=*) | |
| + site="$ac_optarg" ;; | |
| + | |
| + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) | |
| + ac_prev=srcdir ;; | |
| + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) | |
| + srcdir="$ac_optarg" ;; | |
| + | |
| + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | |
| + | --syscon | --sysco | --sysc | --sys | --sy) | |
| + ac_prev=sysconfdir ;; | |
| + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | |
| + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) | |
| + sysconfdir="$ac_optarg" ;; | |
| + | |
| + -target | --target | --targe | --targ | --tar | --ta | --t) | |
| + ac_prev=target ;; | |
| + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) | |
| + target="$ac_optarg" ;; | |
| + | |
| + -v | -verbose | --verbose | --verbos | --verbo | --verb) | |
| + verbose=yes ;; | |
| + | |
| + -version | --version | --versio | --versi | --vers) | |
| + echo "configure generated by autoconf version 2.13" | |
| + exit 0 ;; | |
| + | |
| + -with-* | --with-*) | |
| + ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` | |
| + # Reject names that are not valid shell variable names. | |
| + if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then | |
| + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } | |
| + fi | |
| + ac_package=`echo $ac_package| sed 's/-/_/g'` | |
| + case "$ac_option" in | |
| + *=*) ;; | |
| + *) ac_optarg=yes ;; | |
| + esac | |
| + eval "with_${ac_package}='$ac_optarg'" ;; | |
| + | |
| + -without-* | --without-*) | |
| + ac_package=`echo $ac_option|sed -e 's/-*without-//'` | |
| + # Reject names that are not valid shell variable names. | |
| + if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then | |
| + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } | |
| + fi | |
| + ac_package=`echo $ac_package| sed 's/-/_/g'` | |
| + eval "with_${ac_package}=no" ;; | |
| + | |
| + --x) | |
| + # Obsolete; use --with-x. | |
| + with_x=yes ;; | |
| + | |
| + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | |
| + | --x-incl | --x-inc | --x-in | --x-i) | |
| + ac_prev=x_includes ;; | |
| + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | |
| + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) | |
| + x_includes="$ac_optarg" ;; | |
| + | |
| + -x-libraries | --x-libraries | --x-librarie | --x-librari \ | |
| + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) | |
| + ac_prev=x_libraries ;; | |
| + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | |
| + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) | |
| + x_libraries="$ac_optarg" ;; | |
| + | |
| + -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } | |
| + ;; | |
| + | |
| + *) | |
| + if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then | |
| + echo "configure: warning: $ac_option: invalid host type" 1>&2 | |
| + fi | |
| + if test "x$nonopt" != xNONE; then | |
| + { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } | |
| + fi | |
| + nonopt="$ac_option" | |
| + ;; | |
| + | |
| + esac | |
| +done | |
| + | |
| +if test -n "$ac_prev"; then | |
| + { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } | |
| +fi | |
| + | |
| +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 | |
| + | |
| +# File descriptor usage: | |
| +# 0 standard input | |
| +# 1 file creation | |
| +# 2 errors and warnings | |
| +# 3 some systems may open it to /dev/tty | |
| +# 4 used on the Kubota Titan | |
| +# 6 checking for... messages and results | |
| +# 5 compiler messages saved in config.log | |
| +if test "$silent" = yes; then | |
| + exec 6>/dev/null | |
| +else | |
| + exec 6>&1 | |
| +fi | |
| +exec 5>./config.log | |
| + | |
| +echo "\ | |
| +This file contains any messages produced by compilers while | |
| +running configure, to aid debugging if configure makes a mistake. | |
| +" 1>&5 | |
| + | |
| +# Strip out --no-create and --no-recursion so they do not pile up. | |
| +# Also quote any args containing shell metacharacters. | |
| +ac_configure_args= | |
| +for ac_arg | |
| +do | |
| + case "$ac_arg" in | |
| + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | |
| + | --no-cr | --no-c) ;; | |
| + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | |
| + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; | |
| + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) | |
| + ac_configure_args="$ac_configure_args '$ac_arg'" ;; | |
| + *) ac_configure_args="$ac_configure_args $ac_arg" ;; | |
| + esac | |
| +done | |
| + | |
| +# NLS nuisances. | |
| +# Only set these to C if already set. These must not be set unconditionally | |
| +# because not all systems understand e.g. LANG=C (notably SCO). | |
| +# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! | |
| +# Non-C LC_CTYPE values break the ctype check. | |
| +if test "${LANG+set}" = set; then LANG=C; export LANG; fi | |
| +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi | |
| +if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi | |
| +if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi | |
| + | |
| +# confdefs.h avoids OS command line length limits that DEFS can exceed. | |
| +rm -rf conftest* confdefs.h | |
| +# AIX cpp loses on an empty file, so make sure it contains at least a newline. | |
| +echo > confdefs.h | |
| + | |
| +# A filename unique to this package, relative to the directory that | |
| +# configure is in, which we can look for to find out if srcdir is correct. | |
| +ac_unique_file=main.c | |
| + | |
| +# Find the source files, if location was not specified. | |
| +if test -z "$srcdir"; then | |
| + ac_srcdir_defaulted=yes | |
| + # Try the directory containing this script, then its parent. | |
| + ac_prog=$0 | |
| + ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` | |
| + test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. | |
| + srcdir=$ac_confdir | |
| + if test ! -r $srcdir/$ac_unique_file; then | |
| + srcdir=.. | |
| + fi | |
| +else | |
| + ac_srcdir_defaulted=no | |
| +fi | |
| +if test ! -r $srcdir/$ac_unique_file; then | |
| + if test "$ac_srcdir_defaulted" = yes; then | |
| + { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } | |
| + else | |
| + { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } | |
| + fi | |
| +fi | |
| +srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` | |
| + | |
| +# Prefer explicitly selected file to automatically selected ones. | |
| +if test -z "$CONFIG_SITE"; then | |
| + if test "x$prefix" != xNONE; then | |
| + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" | |
| + else | |
| + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" | |
| + fi | |
| +fi | |
| +for ac_site_file in $CONFIG_SITE; do | |
| + if test -r "$ac_site_file"; then | |
| + echo "loading site script $ac_site_file" | |
| + . "$ac_site_file" | |
| + fi | |
| +done | |
| + | |
| +if test -r "$cache_file"; then | |
| + echo "loading cache $cache_file" | |
| + . $cache_file | |
| +else | |
| + echo "creating cache $cache_file" | |
| + > $cache_file | |
| +fi | |
| + | |
| +ac_ext=c | |
| +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. | |
| +ac_cpp='$CPP $CPPFLAGS' | |
| +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' | |
| +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' | |
| +cross_compiling=$ac_cv_prog_cc_cross | |
| + | |
| +ac_exeext= | |
| +ac_objext=o | |
| +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then | |
| + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. | |
| + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then | |
| + ac_n= ac_c=' | |
| +' ac_t=' ' | |
| + else | |
| + ac_n=-n ac_c= ac_t= | |
| + fi | |
| +else | |
| + ac_n= ac_c='\c' ac_t= | |
| +fi | |
| + | |
| + | |
| + | |
| +# Check for programs. | |
| + | |
| +# Extract the first word of "gcc", so it can be a program name with args. | |
| +set dummy gcc; ac_word=$2 | |
| +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 | |
| +echo "configure:531: checking for $ac_word" >&5 | |
| +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then | |
| + echo $ac_n "(cached) $ac_c" 1>&6 | |
| +else | |
| + if test -n "$CC"; then | |
| + ac_cv_prog_CC="$CC" # Let the user override the test. | |
| +else | |
| + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" | |
| + ac_dummy="$PATH" | |
| + for ac_dir in $ac_dummy; do | |
| + test -z "$ac_dir" && ac_dir=. | |
| + if test -f $ac_dir/$ac_word; then | |
| + ac_cv_prog_CC="gcc" | |
| + break | |
| + fi | |
| + done | |
| + IFS="$ac_save_ifs" | |
| +fi | |
| +fi | |
| +CC="$ac_cv_prog_CC" | |
| +if test -n "$CC"; then | |
| + echo "$ac_t""$CC" 1>&6 | |
| +else | |
| + echo "$ac_t""no" 1>&6 | |
| +fi | |
| + | |
| +if test -z "$CC"; then | |
| + # Extract the first word of "cc", so it can be a program name with args. | |
| +set dummy cc; ac_word=$2 | |
| +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 | |
| +echo "configure:561: checking for $ac_word" >&5 | |
| +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then | |
| + echo $ac_n "(cached) $ac_c" 1>&6 | |
| +else | |
| + if test -n "$CC"; then | |
| + ac_cv_prog_CC="$CC" # Let the user override the test. | |
| +else | |
| + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" | |
| + ac_prog_rejected=no | |
| + ac_dummy="$PATH" | |
| + for ac_dir in $ac_dummy; do | |
| + test -z "$ac_dir" && ac_dir=. | |
| + if test -f $ac_dir/$ac_word; then | |
| + if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then | |
| + ac_prog_rejected=yes | |
| + continue | |
| + fi | |
| + ac_cv_prog_CC="cc" | |
| + break | |
| + fi | |
| + done | |
| + IFS="$ac_save_ifs" | |
| +if test $ac_prog_rejected = yes; then | |
| + # We found a bogon in the path, so make sure we never use it. | |
| + set dummy $ac_cv_prog_CC | |
| + shift | |
| + if test $# -gt 0; then | |
| + # We chose a different compiler from the bogus one. | |
| + # However, it has the same basename, so the bogon will be chosen | |
| + # first if we set CC to just the basename; use the full file name. | |
| + shift | |
| + set dummy "$ac_dir/$ac_word" "$@" | |
| + shift | |
| + ac_cv_prog_CC="$@" | |
| + fi | |
| +fi | |
| +fi | |
| +fi | |
| +CC="$ac_cv_prog_CC" | |
| +if test -n "$CC"; then | |
| + echo "$ac_t""$CC" 1>&6 | |
| +else | |
| + echo "$ac_t""no" 1>&6 | |
| +fi | |
| + | |
| + if test -z "$CC"; then | |
| + case "`uname -s`" in | |
| + *win32* | *WIN32*) | |
| + # Extract the first word of "cl", so it can be a program name with args. | |
| +set dummy cl; ac_word=$2 | |
| +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 | |
| +echo "configure:612: checking for $ac_word" >&5 | |
| +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then | |
| + echo $ac_n "(cached) $ac_c" 1>&6 | |
| +else | |
| + if test -n "$CC"; then | |
| + ac_cv_prog_CC="$CC" # Let the user override the test. | |
| +else | |
| + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" | |
| + ac_dummy="$PATH" | |
| + for ac_dir in $ac_dummy; do | |
| + test -z "$ac_dir" && ac_dir=. | |
| + if test -f $ac_dir/$ac_word; then | |
| + ac_cv_prog_CC="cl" | |
| + break | |
| + fi | |
| + done | |
| + IFS="$ac_save_ifs" | |
| +fi | |
| +fi | |
| +CC="$ac_cv_prog_CC" | |
| +if test -n "$CC"; then | |
| + echo "$ac_t""$CC" 1>&6 | |
| +else | |
| + echo "$ac_t""no" 1>&6 | |
| +fi | |
| + ;; | |
| + esac | |
| + fi | |
| + test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } | |
| +fi | |
| + | |
| +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 | |
| +echo "configure:644: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 | |
| + | |
| +ac_ext=c | |
| +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. | |
| +ac_cpp='$CPP $CPPFLAGS' | |
| +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' | |
| +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' | |
| +cross_compiling=$ac_cv_prog_cc_cross | |
| + | |
| +cat > conftest.$ac_ext << EOF | |
| + | |
| +#line 655 "configure" | |
| +#include "confdefs.h" | |
| + | |
| +main(){return(0);} | |
| +EOF | |
| +if { (eval echo configure:660: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then | |
| + ac_cv_prog_cc_works=yes | |
| + # If we can't run a trivial program, we are probably using a cross compiler. | |
| + if (./conftest; exit) 2>/dev/null; then | |
| + ac_cv_prog_cc_cross=no | |
| + else | |
| + ac_cv_prog_cc_cross=yes | |
| + fi | |
| +else | |
| + echo "configure: failed program was:" >&5 | |
| + cat conftest.$ac_ext >&5 | |
| + ac_cv_prog_cc_works=no | |
| +fi | |
| +rm -fr conftest* | |
| +ac_ext=c | |
| +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. | |
| +ac_cpp='$CPP $CPPFLAGS' | |
| +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' | |
| +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' | |
| +cross_compiling=$ac_cv_prog_cc_cross | |
| + | |
| +echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 | |
| +if test $ac_cv_prog_cc_works = no; then | |
| + { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } | |
| +fi | |
| +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 | |
| +echo "configure:686: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 | |
| +echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 | |
| +cross_compiling=$ac_cv_prog_cc_cross | |
| + | |
| +echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 | |
| +echo "configure:691: checking whether we are using GNU C" >&5 | |
| +if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then | |
| + echo $ac_n "(cached) $ac_c" 1>&6 | |
| +else | |
| + cat > conftest.c <<EOF | |
| +#ifdef __GNUC__ | |
| + yes; | |
| +#endif | |
| +EOF | |
| +if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:700: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then | |
| + ac_cv_prog_gcc=yes | |
| +else | |
| + ac_cv_prog_gcc=no | |
| +fi | |
| +fi | |
| + | |
| +echo "$ac_t""$ac_cv_prog_gcc" 1>&6 | |
| + | |
| +if test $ac_cv_prog_gcc = yes; then | |
| + GCC=yes | |
| +else | |
| + GCC= | |
| +fi | |
| + | |
| +ac_test_CFLAGS="${CFLAGS+set}" | |
| +ac_save_CFLAGS="$CFLAGS" | |
| +CFLAGS= | |
| +echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 | |
| +echo "configure:719: checking whether ${CC-cc} accepts -g" >&5 | |
| +if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then | |
| + echo $ac_n "(cached) $ac_c" 1>&6 | |
| +else | |
| + echo 'void f(){}' > conftest.c | |
| +if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then | |
| + ac_cv_prog_cc_g=yes | |
| +else | |
| + ac_cv_prog_cc_g=no | |
| +fi | |
| +rm -f conftest* | |
| + | |
| +fi | |
| + | |
| +echo "$ac_t""$ac_cv_prog_cc_g" 1>&6 | |
| +if test "$ac_test_CFLAGS" = set; then | |
| + CFLAGS="$ac_save_CFLAGS" | |
| +elif test $ac_cv_prog_cc_g = yes; then | |
| + if test "$GCC" = yes; then | |
| + CFLAGS="-g -O2" | |
| + else | |
| + CFLAGS="-g" | |
| + fi | |
| +else | |
| + if test "$GCC" = yes; then | |
| + CFLAGS="-O2" | |
| + else | |
| + CFLAGS= | |
| + fi | |
| +fi | |
| + | |
| + | |
| +# Check for header files. | |
| + | |
| +echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 | |
| +echo "configure:754: checking how to run the C preprocessor" >&5 | |
| +# On Suns, sometimes $CPP names a directory. | |
| +if test -n "$CPP" && test -d "$CPP"; then | |
| + CPP= | |
| +fi | |
| +if test -z "$CPP"; then | |
| +if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then | |
| + echo $ac_n "(cached) $ac_c" 1>&6 | |
| +else | |
| + # This must be in double quotes, not single quotes, because CPP may get | |
| + # substituted into the Makefile and "${CC-cc}" will confuse make. | |
| + CPP="${CC-cc} -E" | |
| + # On the NeXT, cc -E runs the code through the compiler's parser, | |
| + # not just through cpp. | |
| + cat > conftest.$ac_ext <<EOF | |
| +#line 769 "configure" | |
| +#include "confdefs.h" | |
| +#include <assert.h> | |
| +Syntax Error | |
| +EOF | |
| +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" | |
| +{ (eval echo configure:775: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } | |
| +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` | |
| +if test -z "$ac_err"; then | |
| + : | |
| +else | |
| + echo "$ac_err" >&5 | |
| + echo "configure: failed program was:" >&5 | |
| + cat conftest.$ac_ext >&5 | |
| + rm -rf conftest* | |
| + CPP="${CC-cc} -E -traditional-cpp" | |
| + cat > conftest.$ac_ext <<EOF | |
| +#line 786 "configure" | |
| +#include "confdefs.h" | |
| +#include <assert.h> | |
| +Syntax Error | |
| +EOF | |
| +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" | |
| +{ (eval echo configure:792: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } | |
| +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` | |
| +if test -z "$ac_err"; then | |
| + : | |
| +else | |
| + echo "$ac_err" >&5 | |
| + echo "configure: failed program was:" >&5 | |
| + cat conftest.$ac_ext >&5 | |
| + rm -rf conftest* | |
| + CPP="${CC-cc} -nologo -E" | |
| + cat > conftest.$ac_ext <<EOF | |
| +#line 803 "configure" | |
| +#include "confdefs.h" | |
| +#include <assert.h> | |
| +Syntax Error | |
| +EOF | |
| +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" | |
| +{ (eval echo configure:809: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } | |
| +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` | |
| +if test -z "$ac_err"; then | |
| + : | |
| +else | |
| + echo "$ac_err" >&5 | |
| + echo "configure: failed program was:" >&5 | |
| + cat conftest.$ac_ext >&5 | |
| + rm -rf conftest* | |
| + CPP=/lib/cpp | |
| +fi | |
| +rm -f conftest* | |
| +fi | |
| +rm -f conftest* | |
| +fi | |
| +rm -f conftest* | |
| + ac_cv_prog_CPP="$CPP" | |
| +fi | |
| + CPP="$ac_cv_prog_CPP" | |
| +else | |
| + ac_cv_prog_CPP="$CPP" | |
| +fi | |
| +echo "$ac_t""$CPP" 1>&6 | |
| + | |
| +echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 | |
| +echo "configure:834: checking for ANSI C header files" >&5 | |
| +if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then | |
| + echo $ac_n "(cached) $ac_c" 1>&6 | |
| +else | |
| + cat > conftest.$ac_ext <<EOF | |
| +#line 839 "configure" | |
| +#include "confdefs.h" | |
| +#include <stdlib.h> | |
| +#include <stdarg.h> | |
| +#include <string.h> | |
| +#include <float.h> | |
| +EOF | |
| +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" | |
| +{ (eval echo configure:847: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } | |
| +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` | |
| +if test -z "$ac_err"; then | |
| + rm -rf conftest* | |
| + ac_cv_header_stdc=yes | |
| +else | |
| + echo "$ac_err" >&5 | |
| + echo "configure: failed program was:" >&5 | |
| + cat conftest.$ac_ext >&5 | |
| + rm -rf conftest* | |
| + ac_cv_header_stdc=no | |
| +fi | |
| +rm -f conftest* | |
| + | |
| +if test $ac_cv_header_stdc = yes; then | |
| + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. | |
| +cat > conftest.$ac_ext <<EOF | |
| +#line 864 "configure" | |
| +#include "confdefs.h" | |
| +#include <string.h> | |
| +EOF | |
| +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | | |
| + egrep "memchr" >/dev/null 2>&1; then | |
| + : | |
| +else | |
| + rm -rf conftest* | |
| + ac_cv_header_stdc=no | |
| +fi | |
| +rm -f conftest* | |
| + | |
| +fi | |
| + | |
| +if test $ac_cv_header_stdc = yes; then | |
| + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. | |
| +cat > conftest.$ac_ext <<EOF | |
| +#line 882 "configure" | |
| +#include "confdefs.h" | |
| +#include <stdlib.h> | |
| +EOF | |
| +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | | |
| + egrep "free" >/dev/null 2>&1; then | |
| + : | |
| +else | |
| + rm -rf conftest* | |
| + ac_cv_header_stdc=no | |
| +fi | |
| +rm -f conftest* | |
| + | |
| +fi | |
| + | |
| +if test $ac_cv_header_stdc = yes; then | |
| + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. | |
| +if test "$cross_compiling" = yes; then | |
| + : | |
| +else | |
| + cat > conftest.$ac_ext <<EOF | |
| +#line 903 "configure" | |
| +#include "confdefs.h" | |
| +#include <ctype.h> | |
| +#define ISLOWER(c) ('a' <= (c) && (c) <= 'z') | |
| +#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) | |
| +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) | |
| +int main () { int i; for (i = 0; i < 256; i++) | |
| +if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); | |
| +exit (0); } | |
| + | |
| +EOF | |
| +if { (eval echo configure:914: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null | |
| +then | |
| + : | |
| +else | |
| + echo "configure: failed program was:" >&5 | |
| + cat conftest.$ac_ext >&5 | |
| + rm -fr conftest* | |
| + ac_cv_header_stdc=no | |
| +fi | |
| +rm -fr conftest* | |
| +fi | |
| + | |
| +fi | |
| +fi | |
| + | |
| +echo "$ac_t""$ac_cv_header_stdc" 1>&6 | |
| +if test $ac_cv_header_stdc = yes; then | |
| + cat >> confdefs.h <<\EOF | |
| +#define STDC_HEADERS 1 | |
| +EOF | |
| + | |
| +fi | |
| + | |
| + | |
| +# ...and output. | |
| + | |
| +trap '' 1 2 15 | |
| +cat > confcache <<\EOF | |
| +# This file is a shell script that caches the results of configure | |
| +# tests run on this system so they can be shared between configure | |
| +# scripts and configure runs. It is not useful on other systems. | |
| +# If it contains results you don't want to keep, you may remove or edit it. | |
| +# | |
| +# By default, configure uses ./config.cache as the cache file, | |
| +# creating it if it does not exist already. You can give configure | |
| +# the --cache-file=FILE option to use a different cache file; that is | |
| +# what configure does when it calls configure scripts in | |
| +# subdirectories, so they share the cache. | |
| +# Giving --cache-file=/dev/null disables caching, for debugging configure. | |
| +# config.status only pays attention to the cache file if you give it the | |
| +# --recheck option to rerun configure. | |
| +# | |
| +EOF | |
| +# The following way of writing the cache mishandles newlines in values, | |
| +# but we know of no workaround that is simple, portable, and efficient. | |
| +# So, don't put newlines in cache variables' values. | |
| +# Ultrix sh set writes to stderr and can't be redirected directly, | |
| +# and sets the high bit in the cache file unless we assign to the vars. | |
| +(set) 2>&1 | | |
| + case `(ac_space=' '; set | grep ac_space) 2>&1` in | |
| + *ac_space=\ *) | |
| + # `set' does not quote correctly, so add quotes (double-quote substitution | |
| + # turns \\\\ into \\, and sed turns \\ into \). | |
| + sed -n \ | |
| + -e "s/'/'\\\\''/g" \ | |
| + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" | |
| + ;; | |
| + *) | |
| + # `set' quotes correctly as required by POSIX, so do not add quotes. | |
| + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' | |
| + ;; | |
| + esac >> confcache | |
| +if cmp -s $cache_file confcache; then | |
| + : | |
| +else | |
| + if test -w $cache_file; then | |
| + echo "updating cache $cache_file" | |
| + cat confcache > $cache_file | |
| + else | |
| + echo "not updating unwritable cache $cache_file" | |
| + fi | |
| +fi | |
| +rm -f confcache | |
| + | |
| +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 | |
| + | |
| +test "x$prefix" = xNONE && prefix=$ac_default_prefix | |
| +# Let make expand exec_prefix. | |
| +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' | |
| + | |
| +# Any assignment to VPATH causes Sun make to only execute | |
| +# the first set of double-colon rules, so remove it if not needed. | |
| +# If there is a colon in the path, we need to keep it. | |
| +if test "x$srcdir" = x.; then | |
| + ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' | |
| +fi | |
| + | |
| +trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 | |
| + | |
| +# Transform confdefs.h into DEFS. | |
| +# Protect against shell expansion while executing Makefile rules. | |
| +# Protect against Makefile macro expansion. | |
| +cat > conftest.defs <<\EOF | |
| +s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g | |
| +s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g | |
| +s%\[%\\&%g | |
| +s%\]%\\&%g | |
| +s%\$%$$%g | |
| +EOF | |
| +DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '` | |
| +rm -f conftest.defs | |
| + | |
| + | |
| +# Without the "./", some shells look in PATH for config.status. | |
| +: ${CONFIG_STATUS=./config.status} | |
| + | |
| +echo creating $CONFIG_STATUS | |
| +rm -f $CONFIG_STATUS | |
| +cat > $CONFIG_STATUS <<EOF | |
| +#! /bin/sh | |
| +# Generated automatically by configure. | |
| +# Run this file to recreate the current configuration. | |
| +# This directory was configured as follows, | |
| +# on host `(hostname || uname -n) 2>/dev/null | sed 1q`: | |
| +# | |
| +# $0 $ac_configure_args | |
| +# | |
| +# Compiler output produced by configure, useful for debugging | |
| +# configure, is in ./config.log if it exists. | |
| + | |
| +ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" | |
| +for ac_option | |
| +do | |
| + case "\$ac_option" in | |
| + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) | |
| + echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" | |
| + exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; | |
| + -version | --version | --versio | --versi | --vers | --ver | --ve | --v) | |
| + echo "$CONFIG_STATUS generated by autoconf version 2.13" | |
| + exit 0 ;; | |
| + -help | --help | --hel | --he | --h) | |
| + echo "\$ac_cs_usage"; exit 0 ;; | |
| + *) echo "\$ac_cs_usage"; exit 1 ;; | |
| + esac | |
| +done | |
| + | |
| +ac_given_srcdir=$srcdir | |
| + | |
| +trap 'rm -fr `echo "Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 | |
| +EOF | |
| +cat >> $CONFIG_STATUS <<EOF | |
| + | |
| +# Protect against being on the right side of a sed subst in config.status. | |
| +sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g; | |
| + s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF | |
| +$ac_vpsub | |
| +$extrasub | |
| +s%@SHELL@%$SHELL%g | |
| +s%@CFLAGS@%$CFLAGS%g | |
| +s%@CPPFLAGS@%$CPPFLAGS%g | |
| +s%@CXXFLAGS@%$CXXFLAGS%g | |
| +s%@FFLAGS@%$FFLAGS%g | |
| +s%@DEFS@%$DEFS%g | |
| +s%@LDFLAGS@%$LDFLAGS%g | |
| +s%@LIBS@%$LIBS%g | |
| +s%@exec_prefix@%$exec_prefix%g | |
| +s%@prefix@%$prefix%g | |
| +s%@program_transform_name@%$program_transform_name%g | |
| +s%@bindir@%$bindir%g | |
| +s%@sbindir@%$sbindir%g | |
| +s%@libexecdir@%$libexecdir%g | |
| +s%@datadir@%$datadir%g | |
| +s%@sysconfdir@%$sysconfdir%g | |
| +s%@sharedstatedir@%$sharedstatedir%g | |
| +s%@localstatedir@%$localstatedir%g | |
| +s%@libdir@%$libdir%g | |
| +s%@includedir@%$includedir%g | |
| +s%@oldincludedir@%$oldincludedir%g | |
| +s%@infodir@%$infodir%g | |
| +s%@mandir@%$mandir%g | |
| +s%@CC@%$CC%g | |
| +s%@CPP@%$CPP%g | |
| + | |
| +CEOF | |
| +EOF | |
| + | |
| +cat >> $CONFIG_STATUS <<\EOF | |
| + | |
| +# Split the substitutions into bite-sized pieces for seds with | |
| +# small command number limits, like on Digital OSF/1 and HP-UX. | |
| +ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. | |
| +ac_file=1 # Number of current file. | |
| +ac_beg=1 # First line for current file. | |
| +ac_end=$ac_max_sed_cmds # Line after last line for current file. | |
| +ac_more_lines=: | |
| +ac_sed_cmds="" | |
| +while $ac_more_lines; do | |
| + if test $ac_beg -gt 1; then | |
| + sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file | |
| + else | |
| + sed "${ac_end}q" conftest.subs > conftest.s$ac_file | |
| + fi | |
| + if test ! -s conftest.s$ac_file; then | |
| + ac_more_lines=false | |
| + rm -f conftest.s$ac_file | |
| + else | |
| + if test -z "$ac_sed_cmds"; then | |
| + ac_sed_cmds="sed -f conftest.s$ac_file" | |
| + else | |
| + ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" | |
| + fi | |
| + ac_file=`expr $ac_file + 1` | |
| + ac_beg=$ac_end | |
| + ac_end=`expr $ac_end + $ac_max_sed_cmds` | |
| + fi | |
| +done | |
| +if test -z "$ac_sed_cmds"; then | |
| + ac_sed_cmds=cat | |
| +fi | |
| +EOF | |
| + | |
| +cat >> $CONFIG_STATUS <<EOF | |
| + | |
| +CONFIG_FILES=\${CONFIG_FILES-"Makefile"} | |
| +EOF | |
| +cat >> $CONFIG_STATUS <<\EOF | |
| +for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then | |
| + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". | |
| + case "$ac_file" in | |
| + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` | |
| + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; | |
| + *) ac_file_in="${ac_file}.in" ;; | |
| + esac | |
| + | |
| + # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. | |
| + | |
| + # Remove last slash and all that follows it. Not all systems have dirname. | |
| + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` | |
| + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then | |
| + # The file is in a subdirectory. | |
| + test ! -d "$ac_dir" && mkdir "$ac_dir" | |
| + ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" | |
| + # A "../" for each directory in $ac_dir_suffix. | |
| + ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` | |
| + else | |
| + ac_dir_suffix= ac_dots= | |
| + fi | |
| + | |
| + case "$ac_given_srcdir" in | |
| + .) srcdir=. | |
| + if test -z "$ac_dots"; then top_srcdir=. | |
| + else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; | |
| + /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; | |
| + *) # Relative path. | |
| + srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" | |
| + top_srcdir="$ac_dots$ac_given_srcdir" ;; | |
| + esac | |
| + | |
| + | |
| + echo creating "$ac_file" | |
| + rm -f "$ac_file" | |
| + configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." | |
| + case "$ac_file" in | |
| + *Makefile*) ac_comsub="1i\\ | |
| +# $configure_input" ;; | |
| + *) ac_comsub= ;; | |
| + esac | |
| + | |
| + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` | |
| + sed -e "$ac_comsub | |
| +s%@configure_input@%$configure_input%g | |
| +s%@srcdir@%$srcdir%g | |
| +s%@top_srcdir@%$top_srcdir%g | |
| +" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file | |
| +fi; done | |
| +rm -f conftest.s* | |
| + | |
| +EOF | |
| +cat >> $CONFIG_STATUS <<EOF | |
| + | |
| +EOF | |
| +cat >> $CONFIG_STATUS <<\EOF | |
| + | |
| +exit 0 | |
| +EOF | |
| +chmod +x $CONFIG_STATUS | |
| +rm -fr confdefs* $ac_clean_files | |
| +test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 | |
| + | |
| + | |
| --- vbcc-0.7.orig/share/vbcc/conf/i386 | |
| +++ vbcc-0.7/share/vbcc/conf/i386 | |
| +-pp=/usr/lib/vbcc/vcpp -I/usr/share/vbcc/arch/i386/include -D__I386__ -+ %s %s %s | |
| +-ppv=/usr/lib/vbcc/vcpp -I/usr/share/vbcc/arch/i386/include -D__I386__ -+ %s %s %s | |
| +-cc=/usr/lib/vbcc/vbcci386 -quiet %s -o=%s %s -O=%ld | |
| +-ccv=/usr/lib/vbcc/vbcci386 -I/usr/share/vbcc/arch/i386/include %s -o=%s %s -O=%ld | |
| +-as=echo "Don't know how to assemble i386 code" 1>&2; exit 0 | |
| +-ld=echo "Don't know how to link i386 code" 1>&2; exit 0 | |
| +-rm=rm %s | |
| +-rmv=rm %s | |
| --- vbcc-0.7.orig/share/vbcc/conf/m68k | |
| +++ vbcc-0.7/share/vbcc/conf/m68k | |
| +-pp=/usr/lib/vbcc/vcpp -I/usr/share/vbcc/arch/m68k/include -D__M68K__ -+ %s %s %s | |
| +-ppv=/usr/lib/vbcc/vcpp -I/usr/share/vbcc/arch/m68k/include -D__M68K__ -+ %s %s %s | |
| +-cc=/usr/lib/vbcc/vbccm68k -quiet %s -o=%s %s -O=%ld | |
| +-ccv=/usr/lib/vbcc/vbccm68k -I/usr/share/vbcc/arch/m68k/include %s -o=%s %s -O=%ld | |
| +-as=echo "Don't know how to assemble m68k code" 1>&2; exit 0 | |
| +-ld=echo "Don't know how to link m68k code" 1>&2; exit 0 | |
| +-rm=rm %s | |
| +-rmv=rm %s | |
| --- vbcc-0.7.orig/share/vbcc/conf/alpha | |
| +++ vbcc-0.7/share/vbcc/conf/alpha | |
| +-pp=/usr/lib/vbcc/vcpp -I/usr/share/vbcc/arch/alpha/include -D__ALPHA__ -+ %s %s %s | |
| +-ppv=/usr/lib/vbcc/vcpp -I/usr/share/vbcc/arch/alpha/include -D__ALPHAI386__ -+ %s %s %s | |
| +-cc=/usr/lib/vbcc/vbccalpha -quiet %s -o=%s %s -O=%ld | |
| +-ccv=/usr/lib/vbcc/vbccalpha -I/usr/share/vbcc/arch/alpha/include %s -o=%s %s -O=%ld | |
| +-as=echo "Don't know how to assemble Alpha code" 1>&2; exit 0 | |
| +-ld=echo "Don't know how to link Alpha code" 1>&2; exit 0 | |
| +-rm=rm %s | |
| +-rmv=rm %s | |
| --- vbcc-0.7.orig/share/vbcc/conf/ppc | |
| +++ vbcc-0.7/share/vbcc/conf/ppc | |
| +-pp=/usr/lib/vbcc/vcpp -I/usr/share/vbcc/arch/ppc/include -D__PPC__ -+ %s %s %s | |
| +-ppv=/usr/lib/vbcc/vcpp -I/usr/share/vbcc/arch/ppc/include -D__PPC__ -+ %s %s %s | |
| +-cc=/usr/lib/vbcc/vbccppc -quiet %s -o=%s %s -O=%ld | |
| +-ccv=/usr/lib/vbcc/vbccppc -I/usr/share/vbcc/arch/ppc/include %s -o=%s %s -O=%ld | |
| +-as=echo "Don't know how to assemble PowerPC code" 1>&2; exit 0 | |
| +-ld=echo "Don't know how to link PowerPC code" 1>&2; exit 0 | |
| +-rm=rm %s | |
| +-rmv=rm %s | |
| --- vbcc-0.7.orig/share/vbcc/conf/z | |
| +++ vbcc-0.7/share/vbcc/conf/z | |
| +-pp=/usr/lib/vbcc/vcpp -I/usr/share/vbcc/arch/z/include -+ -D__Z__ %s %s %s | |
| +-ppv=/usr/lib/vbcc/vcpp -I/usr/share/vbcc/arch/z/include -+ -D__Z__ %s %s %s | |
| +-cc=/usr/lib/vbcc/vbccz -quiet %s -o=%s %s -O=%ld | |
| +-ccv=/usr/lib/vbcc/vbccz %s -o=%s %s -O=%ld | |
| +-as=cp %s %s | |
| +-ld=echo "Don't know how to link Z-machine code" 1>&2; exit 0 | |
| +-rm=rm %s | |
| --- vbcc-0.7.orig/share/vbcc/conf/c16x | |
| +++ vbcc-0.7/share/vbcc/conf/c16x | |
| +-pp=/usr/lib/vbcc/vcpp -I/usr/share/vbcc/arch/c16x/include -D__C16X__ -+ %s %s %s | |
| +-ppv=/usr/lib/vbcc/vcpp -I/usr/share/vbcc/arch/c16x/include -D__C16X__ -+ %s %s %s | |
| +-cc=/usr/lib/vbcc/vbccc16x -quiet %s -o=%s %s -O=%ld | |
| +-ccv=/usr/lib/vbcc/vbccc16x -I/usr/share/vbcc/arch/c16x/include %s -o=%s %s -O=%ld | |
| +-as=echo "Don't know how to assemble C16X code" 1>&2; exit 0 | |
| +-ld=echo "Don't know how to link C16X code" 1>&2; exit 0 | |
| +-rm=rm %s | |
| +-rmv=rm %s | |
| --- vbcc-0.7.orig/share/vbcc/arch/i386/include/stdarg.h | |
| +++ vbcc-0.7/share/vbcc/arch/i386/include/stdarg.h | |
| +/* stdarg.h | |
| + * vbcc is (c) in 1995-99 by Volker Barthelmann. All code is written by me | |
| + * and may be freely redistributed as long as no modifications are made | |
| + * and nothing is charged for it. | |
| + * Non-commercial usage of vbcc is allowed without any restrictions. | |
| + * Commercial usage needs my written consent. | |
| + * | |
| + * Sending me money, gifts, postcards etc. would of course be very nice | |
| + * and may encourage further development of vbcc, but is not legally or | |
| + * morally necessary to use vbcc. | |
| + */ | |
| + | |
| +#ifndef STDARG_H | |
| +#define STDARG_H | |
| + | |
| +typedef unsigned char *va_list; | |
| + | |
| +#define va_start(ap, lastarg) ((ap) = (va_list)(&lastarg + 1)) | |
| +#define va_arg(ap, type) ((ap) += \ | |
| + (sizeof(type)<sizeof(int)?sizeof(int):sizeof(type)), ((type *)(ap))[-1]) | |
| +#define va_end(ap) ((ap) = 0L) | |
| + | |
| +#endif | |
| + | |
| --- vbcc-0.7.orig/share/vbcc/arch/m68k/include/stdarg.h | |
| +++ vbcc-0.7/share/vbcc/arch/m68k/include/stdarg.h | |
| +/* alpha/m68k.h | |
| + * vbcc is (c) in 1995-99 by Volker Barthelmann. All code is written by me | |
| + * and may be freely redistributed as long as no modifications are made | |
| + * and nothing is charged for it. | |
| + * Non-commercial usage of vbcc is allowed without any restrictions. | |
| + * Commercial usage needs my written consent. | |
| + * | |
| + * Sending me money, gifts, postcards etc. would of course be very nice | |
| + * and may encourage further development of vbcc, but is not legally or | |
| + * morally necessary to use vbcc. | |
| + */ | |
| + | |
| +#ifndef STDARG_H | |
| +#define STDARG_H | |
| + | |
| +typedef unsigned char *va_list; | |
| + | |
| +#define va_start(ap, lastarg) ((ap) = (va_list)(&lastarg + 1)) | |
| +#define va_arg(ap, type) ((ap) += \ | |
| + (sizeof(type)<sizeof(int)?sizeof(int):sizeof(type)), ((type *)(ap))[-1]) | |
| +#define va_end(ap) ((ap) = 0L) | |
| + | |
| +#endif | |
| + | |
| --- vbcc-0.7.orig/share/vbcc/arch/alpha/include/stdarg.h | |
| +++ vbcc-0.7/share/vbcc/arch/alpha/include/stdarg.h | |
| +/* alpha/stdarg.h | |
| + * vbcc is (c) in 1995-99 by Volker Barthelmann. All code is written by me | |
| + * and may be freely redistributed as long as no modifications are made | |
| + * and nothing is charged for it. | |
| + * Non-commercial usage of vbcc is allowed without any restrictions. | |
| + * Commercial usage needs my written consent. | |
| + * | |
| + * Sending me money, gifts, postcards etc. would of course be very nice | |
| + * and may encourage further development of vbcc, but is not legally or | |
| + * morally necessary to use vbcc. | |
| + */ | |
| + | |
| +#ifndef STDARG_H | |
| +#define STDARG_H | |
| + | |
| +typedef struct { | |
| + char *regbase; | |
| + char *membase; | |
| + int arg; | |
| +} va_list; | |
| + | |
| +char *__va_start(void); | |
| +int __va_fixargs(void); | |
| + | |
| +#define va_start(vl,dummy) \ | |
| +(vl.arg=__va_fixargs(),vl.regbase=__va_start(),vl.membase=vl.regbase+(6-vl.arg)*16) | |
| + | |
| +#define va_end(vl) (vl.regbase=vl.membase=0) | |
| + | |
| +#define __va_size(type) ((sizeof(type)+7)/8*8) | |
| +#define va_arg(vl,type) \ | |
| + ( \ | |
| + ((__typeof(type)&15)<=8&&++vl.arg<=6) ? \ | |
| + ( \ | |
| + ((__typeof(type)&15)==5||(__typeof(type)&15)==6) ? \ | |
| + (vl.regbase+=16,*(type *)(vl.regbase-8)) \ | |
| + : \ | |
| + (vl.regbase+=16,*(type *)(vl.regbase-16)) \ | |
| + ) \ | |
| + : \ | |
| + (vl.membase+=__va_size(type),*(type *)(vl.membase-__va_size(type))) \ | |
| + ) | |
| + | |
| +#endif | |
| --- vbcc-0.7.orig/share/vbcc/arch/ppc/include/stdarg.h | |
| +++ vbcc-0.7/share/vbcc/arch/ppc/include/stdarg.h | |
| +/* alpha/m68k.h | |
| + * vbcc is (c) in 1995-99 by Volker Barthelmann. All code is written by me | |
| + * and may be freely redistributed as long as no modifications are made | |
| + * and nothing is charged for it. | |
| + * Non-commercial usage of vbcc is allowed without any restrictions. | |
| + * Commercial usage needs my written consent. | |
| + * | |
| + * Sending me money, gifts, postcards etc. would of course be very nice | |
| + * and may encourage further development of vbcc, but is not legally or | |
| + * morally necessary to use vbcc. | |
| + */ | |
| + | |
| +#ifndef STDARG_H | |
| +#define STDARG_H | |
| + | |
| +typedef struct { | |
| + int gpr; | |
| + int fpr; | |
| + char *regbase; | |
| + char *membase; | |
| +} va_list; | |
| + | |
| +char *__va_start(void); | |
| +char *__va_regbase(void); | |
| +int __va_fixedgpr(void); | |
| +int __va_fixedfpr(void); | |
| + | |
| +#define va_start(vl,dummy) \ | |
| + ( \ | |
| + vl.gpr=__va_fixedgpr(), \ | |
| + vl.fpr=__va_fixedfpr(), \ | |
| + vl.regbase=__va_regbase(), \ | |
| + vl.membase=__va_start() \ | |
| + ) | |
| + | |
| +#define va_end(vl) (vl.regbase=vl.membase=0) | |
| + | |
| +#define __va_size(type) ((sizeof(type)+3)/4*4) | |
| +#define va_arg(vl,type) \ | |
| + (__typeof(type)&15)>8? \ | |
| + (vl.membase+=__va_size(type),((type*)vl.membase)[-1]) \ | |
| + : \ | |
| + ( \ | |
| + (((__typeof(type)&15)==5||(__typeof(type)&15)==6)) ? \ | |
| + ( \ | |
| + ++vl.fpr<=8 ? \ | |
| + ((double*)(vl.regbase+32))[vl.fpr] \ | |
| + : \ | |
| + (vl.membase+=__va_size(type),((type*)vl.membase)[-1]) \ | |
| + ) \ | |
| + : \ | |
| + ( \ | |
| + ++vl.gpr<=8 ? \ | |
| + ((int*)(vl.regbase+0))[vl.gpr] \ | |
| + : \ | |
| + (vl.membase+=__va_size(type),((type*)vl.membase)[-1]) \ | |
| + ) \ | |
| + ) \ | |
| + | |
| +#endif | |
| + | |
| --- vbcc-0.7.orig/share/vbcc/arch/z/include/stdarg.h | |
| +++ vbcc-0.7/share/vbcc/arch/z/include/stdarg.h | |
| +/* z/stdarg.h | |
| + * Copyright (c) 2001, David Given | |
| + * All rights reserved. | |
| + * | |
| + * Permission is hereby granted, free of charge, to any person obtaining a | |
| + * copy of this software and associated documentation files (the "Software"), | |
| + * to deal in the Software without restriction, including without limitation | |
| + * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| + * and/or sell copies of the Software, and to permit persons to whom the | |
| + * Software is furnished to do so, subject to the following conditions: | |
| + * | |
| + * The above copyright notice and this permission notice shall be included in | |
| + * all copies or substantial portions of the Software. | |
| + * | |
| + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
| + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
| + * DEALINGS IN THE SOFTWARE. | |
| + */ | |
| + | |
| +#ifndef STDARG_H | |
| +#define STDARG_H | |
| + | |
| +typedef char* va_list; | |
| +extern va_list __va_start; /* magic */ | |
| + | |
| +#define va_start(ap, lastarg) \ | |
| + ((ap) = __va_start) | |
| +#define va_arg(ap, type) \ | |
| + (((ap) += (sizeof(type)<sizeof(int)) ? sizeof(int) : sizeof(type)), \ | |
| + ((type*)ap)[-1]) | |
| +#define va_end(ap) ((ap) = 0) | |
| + | |
| +#endif | |
| + | |
| --- vbcc-0.7.orig/share/vbcc/arch/z/runtime.s | |
| +++ vbcc-0.7/share/vbcc/arch/z/runtime.s | |
| +! Z-machine C runtime | |
| +! Copyright (c) 2001, David Given | |
| +! All rights reserved. | |
| +! | |
| +! Permission is hereby granted, free of charge, to any person obtaining a | |
| +! copy of this software and associated documentation files (the "Software"), | |
| +! to deal in the Software without restriction, including without limitation | |
| +! the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| +! and/or sell copies of the Software, and to permit persons to whom the | |
| +! Software is furnished to do so, subject to the following conditions: | |
| +! | |
| +! The above copyright notice and this permission notice shall be included in | |
| +! all copies or substantial portions of the Software. | |
| +! | |
| +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
| +! FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
| +! DEALINGS IN THE SOFTWARE. | |
| + | |
| +! There's an Inform bug that stops the @not opcode from assembling correctly, | |
| +! so we have to use a conventional expression. | |
| + | |
| +[ __not q1; | |
| + return ~q1; | |
| +]; | |
| + | |
| +! And the Z-machine doesn't have xor. How bizarre. | |
| + | |
| +[ __xor q1 q2 t; | |
| + return (q1 & (~q2)) | ((~q1) & q2); | |
| +]; | |
| + | |
| +! Unsigned arithmetic is hard. These helper functions do it for us. | |
| +! Thanks to Jay Foad for the algorithm for this. | |
| + | |
| +[ __unsigned_div q1 q2 t; | |
| + if (q1 == 0) | |
| + return q1; | |
| + else if (q2 == 0) | |
| + { | |
| + print "[zlibc error: division by zero in __unsigned_div]"; | |
| + return 0; | |
| + } | |
| + else if (q2 == 1) | |
| + return q1; | |
| + else if ((q1 > 0) && (q2 > 0)) | |
| + return q1/q2; | |
| + | |
| + ! Optimisation query: given that when executing Z-machine instructions, | |
| + ! the decoding is by far the slowest part of the process, is it | |
| + ! useful to have these special cases? | |
| + | |
| + !else if ((q1-32768) < (q2-32768)) | |
| + ! return 0; | |
| + | |
| + else if (q1 == q2) | |
| + return 1; | |
| + else if (q2 < 0) | |
| + { | |
| + ! If q2 is high, then the result can only be 0 or 1. | |
| + ! The only way it can be 1 is if q1 > q2. | |
| + return ((q1-32768) > (q2-32768)); | |
| + } | |
| + | |
| + ! Lose one bit of precision, and do the calculation. | |
| + | |
| + @log_shift q1 0-1 -> t; | |
| + t = t / q2; | |
| + @log_shift t 1 -> t; | |
| + | |
| + ! Now multiply back out and calculate the remainder. This tells | |
| + ! us how much to modify the result by, to restore lost precision. | |
| + | |
| + !print "{", t, "}"; | |
| + !print "[", (q1 - t*q2), ">", q2, "]"; | |
| + | |
| + if (((q1 - t*q2)-32768) >= (q2-32768)) | |
| + t++; | |
| + return t; | |
| +]; | |
| + | |
| +[ __unsigned_mod q1 q2 t; | |
| + t = __unsigned_div(q1, q2) * q2; | |
| + return q1 - t; | |
| +]; | |
| + | |
| +! These wrapper functions do all the long arithmetic. | |
| + | |
| +Array __long_temp1 -> 4; | |
| +Array __long_temp2 -> 4; | |
| +Array __long_temp3 -> 4; | |
| + | |
| +[ __long_copy q1 z; ! z = q1 | |
| + z-->0 = q1-->0; | |
| + z-->1 = q1-->1; | |
| +]; | |
| + | |
| +[ __long_loadconst z hi lo; ! z = hi.lo | |
| + z-->0 = hi; | |
| + z-->1 = lo; | |
| +]; | |
| + | |
| +[ __long_fromint z q1; ! z = (long)q1, with sign extension | |
| + z-->1 = q1; | |
| + if (q1 < 0) | |
| + z-->0 = -1; | |
| + else | |
| + z-->0 = 0; | |
| +]; | |
| + | |
| +[ __long_and q1 q2 z; | |
| + z-->0 = q1-->0 & q2-->0; | |
| + z-->1 = q1-->1 & q2-->1; | |
| +]; | |
| + | |
| +[ __long_or q1 q2 z; | |
| + z-->0 = q1-->0 | q2-->0; | |
| + z-->1 = q1-->1 | q2-->1; | |
| +]; | |
| + | |
| +[ __long_asr q1 q2 z s t; | |
| + if ((q2-->0 ~= 0) || (((q2-->1)-32768) > (31-32768))) | |
| + { | |
| + ! All bits shifted off; so we just propagate the sign. | |
| + | |
| + if (q2-->0 & $8000) | |
| + { | |
| + z-->0 = -1; | |
| + z-->1 = -1; | |
| + } | |
| + else | |
| + { | |
| + z-->0 = 0; | |
| + z-->1 = 0; | |
| + } | |
| + | |
| + return; | |
| + } | |
| + | |
| + q2 = -(q2-->1 & $1F); | |
| + s = 16 + q2; | |
| + | |
| + t = q1-->1; | |
| + @log_shift t q2 -> t; | |
| + z-->1 = t; | |
| + | |
| + t = q1-->0; | |
| + @log_shift t s -> t; | |
| + z-->1 = z-->1 | t; | |
| + | |
| + t = q1-->0; | |
| + @art_shift t q2 -> t; | |
| + z-->0 = t; | |
| +]; | |
| + | |
| +[ __long_lsr q1 q2 z s t; | |
| + if ((q2-->0 ~= 0) || ((q2-->1-32768) > (31-32768))) | |
| + { | |
| + ! All bits shifted off; the result is zero. | |
| + | |
| + z-->0 = 0; | |
| + z-->1 = 0; | |
| + return; | |
| + } | |
| + | |
| + q2 = -(q2-->1 & $1F); | |
| + s = 16 + q2; | |
| + | |
| + t = q1-->1; | |
| + @log_shift t q2 -> t; | |
| + z-->1 = t; | |
| + | |
| + t = q1-->0; | |
| + @log_shift t s -> t; | |
| + z-->1 = z-->1 | t; | |
| + | |
| + t = q1-->0; | |
| + @log_shift t q2 -> t; | |
| + z-->0 = t; | |
| +]; | |
| + | |
| +[ __long_neg q1 z a b; | |
| + a = ~(q1-->0); | |
| + b = ~(q1-->1) + 1; | |
| + if (~~b) | |
| + a++; | |
| + z-->0 = a; | |
| + z-->1 = b; | |
| +]; | |
| + | |
| +[ __long_xor q1 q2 z a b; | |
| + a = q1-->0; | |
| + b = q2-->0; | |
| + z-->0 = (a & (~b)) | ((~a) & b); | |
| + | |
| + a = q1-->1; | |
| + b = q2-->1; | |
| + z-->1 = (a & (~b)) | ((~a) & b); | |
| +]; | |
| + | |
| +[ __long_add q1 q2 z a b c cc; | |
| + ! Add the low word, and detect overflow. | |
| + | |
| + a = q1-->1; | |
| + b = q2-->1; | |
| + c = a + b; | |
| + z-->1 = c; | |
| + @log_shift a 0-15 -> a; | |
| + @log_shift b 0-15 -> b; | |
| + @log_shift c 0-15 -> c; | |
| + cc = a; | |
| + if ((~~a) && b && (~~c)) | |
| + cc = 1; | |
| + else if (a && b && (~~c)) | |
| + cc = 0; | |
| + | |
| + ! Add the high word, plus one if the low word overflowed. | |
| + | |
| + z-->0 = q1-->0 + q2-->0 + cc; | |
| +]; | |
| + | |
| +[ __long_sub q1 q2 z a b c cc; | |
| + ! Subtract the low word, and detect overflow. | |
| + | |
| + a = q1-->1; | |
| + b = q2-->1; | |
| + c = a - b; | |
| + z-->1 = c; | |
| + @log_shift a 0-15 -> a; | |
| + @log_shift b 0-15 -> b; | |
| + @log_shift c 0-15 -> c; | |
| + | |
| + ! Carry table: | |
| + ! a b c c | |
| + ! 0 0 0 0 | |
| + ! 0 0 1 1 | |
| + ! 0 1 0 1 | |
| + ! 0 1 1 1 | |
| + ! 1 0 0 0 | |
| + ! 1 0 1 0 | |
| + ! 1 1 0 0 | |
| + ! 1 1 1 1 | |
| + | |
| + cc = ~~a; | |
| + if ((~~a) && (~~b) && (~~c)) | |
| + cc = 0; | |
| + else if (a && b && c) | |
| + cc = 1; | |
| + | |
| + ! Subtract the high word, plus one if the low word overflowed. | |
| + | |
| + z-->0 = q1-->0 - q2-->0 - cc; | |
| +]; | |
| + | |
| +! Algorithm converted from MIPS assembly, at: | |
| +! http://www.cz3.nus.edu.sg/~wangjs/CZ101/assembly-examples/divide.s | |
| +[ __long_unsigned_divmod q1 q2 d r r1 r2 r3 r4 count t1 t2; | |
| + ! Check for division by zero. | |
| + | |
| + if ((~~(q2-->0)) && (~~(q2-->1))) | |
| + { | |
| + print "[zlibc error: division by zero in __long_unsigned_divmod]"; | |
| + return 0; | |
| + } | |
| + | |
| + count = 0; | |
| + r1 = 0; | |
| + r2 = 0; | |
| + r3 = q1-->0; | |
| + r4 = q1-->1; | |
| + !print "[q1=", r3, " ", r4, " q2=", q2-->0, " ", q2-->1, " "; | |
| + | |
| + do { | |
| + count++; | |
| + | |
| + ! Shift r1..r4 left by one bit. | |
| + | |
| + @log_shift r4 0-15 -> t1; | |
| + @log_shift r4 1 -> r4; | |
| + | |
| + @log_shift r3 0-15 -> t2; | |
| + @log_shift r3 1 -> r3; | |
| + @or r3 t1 -> r3; | |
| + | |
| + @log_shift r2 0-15 -> t1; | |
| + @log_shift r2 1 -> r2; | |
| + @or r2 t2 -> r2; | |
| + | |
| + @log_shift r1 1 -> r1; | |
| + @or r1 t1 -> r1; | |
| + | |
| + ! Subtract divisor from r1..r2. | |
| + | |
| + __long_temp3-->0 = r1; | |
| + __long_temp3-->1 = r2; | |
| + __long_sub(__long_temp3, q2, __long_temp3); | |
| + | |
| + ! Is the remainder non-negative? | |
| + | |
| + if (__long_temp3-->0 >= 0) | |
| + { | |
| + ! Yes. Quotient gets a one; commit subtraction. | |
| + | |
| + r1 = __long_temp3-->0; | |
| + r2 = __long_temp3-->1; | |
| + | |
| + r4 = r4 | 1; | |
| + !print "1"; | |
| + } | |
| + !else print "0"; | |
| + ! Otherwise the quotient gets a zero and the subtraction is not | |
| + ! committed. No operation. | |
| + } until (count == 32); | |
| + | |
| + ! Save results. | |
| + | |
| + !print " r=", r1, " ", r2; | |
| + if (r) | |
| + { | |
| + r-->0 = r1; | |
| + r-->1 = r2; | |
| + } | |
| + !print " d=", r3, " ", r4, "]"; | |
| + if (d) | |
| + { | |
| + d-->0 = r3; | |
| + d-->1 = r4; | |
| + } | |
| +]; | |
| + | |
| +[ __long_div q1 q2 z t sign; | |
| + ! Calculate final sign, and convert parameters to unsigned. | |
| + | |
| + t = q1-->0; | |
| + if (t < 0) | |
| + sign = 1; | |
| + __long_temp1-->0 = t & $7FFF; | |
| + __long_temp1-->1 = q1-->1; | |
| + | |
| + t = q2-->0; | |
| + if (t < 0) | |
| + sign = ~~sign; | |
| + __long_temp2-->0 = t & $7FFF; | |
| + __long_temp2-->1 = q2-->1; | |
| + | |
| + ! Do the actual divide. | |
| + | |
| + __long_unsigned_divmod(__long_temp1, __long_temp2, z, 0); | |
| + | |
| + ! Adjust sign. | |
| + | |
| + if (sign) | |
| + __long_neg(z); | |
| +]; | |
| + | |
| +[ __long_mod q1 q2 z t sign; | |
| + ! Calculate final sign, and convert parameters to unsigned. | |
| + | |
| + t = q1-->0; | |
| + if (t < 0) | |
| + sign = 1; | |
| + __long_temp1-->0 = t & $7FFF; | |
| + __long_temp1-->1 = q1-->1; | |
| + | |
| + t = q2-->0; | |
| + if (t < 0) | |
| + sign = ~~sign; | |
| + __long_temp2-->0 = t & $7FFF; | |
| + __long_temp2-->1 = q2-->1; | |
| + | |
| + ! Do the actual modulo. | |
| + | |
| + __long_unsigned_divmod(__long_temp1, __long_temp2, 0, z); | |
| + | |
| + ! Adjust sign. | |
| + | |
| + if (sign) | |
| + __long_neg(z); | |
| +]; | |
| + | |
| +[ __long_unsigned_div q1 q2 z; | |
| + __long_unsigned_divmod(q1, q2, z, 0); | |
| +]; | |
| + | |
| +[ __long_unsigned_mod q1 q2 z; | |
| + __long_unsigned_divmod(q1, q2, 0, z); | |
| +]; | |
| + | |
| +! Algorithm my own. Probably buggy (although it passes every test I've | |
| +! thrown at it). | |
| +[ __long_mul q1 q2 z a b c d aa bb cc dd sign t; | |
| + ! What we're doing here is long multiplication in base 256; so each | |
| + ! digit is a byte. | |
| + ! | |
| + ! A B C D | |
| + ! * A' B' C' D' | |
| + ! = --------------- | |
| + ! AD' BD' CD' DD' + | |
| + ! BC' CC' DC' + | |
| + ! CB' DB' + | |
| + ! DA' | |
| + ! | |
| + ! We need to add up the columns, remembering to overflow into the | |
| + ! next column. (Don't forget to make everything positive.) | |
| + | |
| + if (q1->0 >= $80) | |
| + { | |
| + ! q1 is negative. | |
| + __long_neg(q1, __long_temp1); | |
| + q1 = __long_temp1; | |
| + sign = 1; | |
| + } | |
| + | |
| + a = q1->0; | |
| + b = q1->1; | |
| + c = q1->2; | |
| + d = q1->3; | |
| + | |
| + if (q2->0 >= $80) | |
| + { | |
| + ! q2 is negative. | |
| + __long_neg(q2, __long_temp1); | |
| + q2 = __long_temp1; | |
| + sign = ~~sign; | |
| + } | |
| + | |
| + aa = q2->0; | |
| + bb = q2->1; | |
| + cc = q2->2; | |
| + dd = q2->3; | |
| + | |
| + ! D column. | |
| + | |
| + t = d*dd; | |
| + z->3 = t; | |
| + @log_shift t 0-8 -> t; | |
| + | |
| + ! C column. | |
| + | |
| + t = t + c*dd + d*cc; | |
| + z->2 = t; | |
| + @log_shift t 0-8 -> t; | |
| + | |
| + ! B column. | |
| + t = t + b*dd + c*cc + d*bb; | |
| + z->1 = t; | |
| + @log_shift t 0-8 -> t; | |
| + | |
| + ! A column. | |
| + t = t + a*dd + b*cc + c*bb + d*aa; | |
| + !t = t & $7F; | |
| + z->0 = t; | |
| + | |
| + ! Apply sign bit. | |
| + | |
| + if (sign) | |
| + __long_neg(z, z); | |
| + | |
| + ! LongMul can't use the same output as one of its inputs. | |
| + !LongMul(__long_temp1, q1, q2); | |
| + !@copy_table __long_temp1 z 4; | |
| +]; | |
| + | |
| +[ __long_compare q1 q2 a b; | |
| + a = q1-->0; | |
| + b = q2-->0; | |
| + if (a == b) | |
| + { | |
| + a = q1-->1 - 32768; | |
| + b = q2-->1 - 32768; | |
| + } | |
| + | |
| + if (a > b) | |
| + return 1; | |
| + if (a < b) | |
| + return -1; | |
| + return 0; | |
| +]; | |
| + | |
| +[ __long_unsigned_compare q1 q2 a b; | |
| + a = q1-->0 - 32768; | |
| + b = q2-->0 - 32768; | |
| + if (a == b) | |
| + { | |
| + a = q1-->1 - 32768; | |
| + b = q2-->1 - 32768; | |
| + } | |
| + | |
| + if (a > b) | |
| + return 1; | |
| + if (a < b) | |
| + return -1; | |
| + return 0; | |
| +]; | |
| + | |
| +! And finally, the routine that calls a C function from Inform. | |
| + | |
| +Constant __c_stack_size 2048; | |
| +Array __c_stack -> __c_stack_size; | |
| + | |
| +[ cinvoke func l0 l1 l2 l3 l4 l5 xp; | |
| + xp = __c_stack + __c_stack_size; | |
| + return func(xp, l0, l1, l2, l3, l4, l5); | |
| +]; | |
| + | |
| --- vbcc-0.7.orig/share/vbcc/arch/c16x/include/stdarg.h | |
| +++ vbcc-0.7/share/vbcc/arch/c16x/include/stdarg.h | |
| +/* alpha/c16x.h | |
| + * vbcc is (c) in 1995-99 by Volker Barthelmann. All code is written by me | |
| + * and may be freely redistributed as long as no modifications are made | |
| + * and nothing is charged for it. | |
| + * Non-commercial usage of vbcc is allowed without any restrictions. | |
| + * Commercial usage needs my written consent. | |
| + * | |
| + * Sending me money, gifts, postcards etc. would of course be very nice | |
| + * and may encourage further development of vbcc, but is not legally or | |
| + * morally necessary to use vbcc. | |
| + */ | |
| + | |
| +#ifndef STDARG_H | |
| +#define STDARG_H | |
| + | |
| +#error stdarg.h is not supported on the C16X | |
| + | |
| +#endif | |
| --- vbcc-0.7.orig/frontend/vc.c | |
| +++ vbcc-0.7/frontend/vc.c | |
| const char *config_name="vc.config"; | |
| const char *search_dirs[]={"","ENV:","VBCC:"}; | |
| char *ul="vlib:%s.lib"; | |
| +#define ASM_SUFFIX ".asm" | |
| #elif defined(WINTEL) | |
| const char *config_name="vc.cfg"; | |
| const char *search_dirs[]={"","%VCCFG%\\"}; | |
| char *ul="-l%s"; | |
| +#define ASM_SUFFIX ".asm" | |
| #else | |
| -const char *config_name="vc.config"; | |
| -const char *search_dirs[]={"","~/","/etc/"}; | |
| +const char *config_name="i386"; | |
| +const char *search_dirs[]={"/usr/share/vbcc/conf/", ""}; | |
| char *ul="-l%s"; | |
| +#define ASM_SUFFIX ".s" | |
| #endif | |
| /* String fuer die Default libraries */ | |
| } | |
| /* MUST come before CCSRC-handling! */ | |
| if(j==SCSRC){ | |
| - file=add_suffix(file,".asm"); | |
| + file=add_suffix(file,ASM_SUFFIX); | |
| if(tfl==ASSRC&&(flags&OUTPUTSET)) file=destname; | |
| sprintf(command,scname,oldfile,file); | |
| if(tfl!=ASSRC) add_name(file,&first_scratch,&last_scratch); | |
| file=add_suffix(file,".scs"); | |
| }else{ | |
| if(++j==tfl-1) file=namebuf; | |
| - file=add_suffix(file,".asm"); | |
| + file=add_suffix(file,ASM_SUFFIX); | |
| } | |
| if(tfl==j+1&&(flags&OUTPUTSET)) file=destname; | |
| sprintf(command,ccname,oldfile,file,options,opt); | |
| if(!strcmp(p,".c")) return PPSRC; | |
| if(!strcmp(p,".i")) return CCSRC; | |
| if(!strcmp(p,".s")) return ASSRC; | |
| - if(!strcmp(p,".asm")) return ASSRC; | |
| + if(!strcmp(p,ASM_SUFFIX)) return ASSRC; | |
| if(!strcmp(p,".scs")) return SCSRC; | |
| if(!strcmp(p,".o")) return OBJ; | |
| if(!strcmp(p,".obj")) return OBJ; | |
| --- vbcc-0.7.orig/main.c | |
| +++ vbcc-0.7/main.c | |
| static char FILE_[]=__FILE__; | |
| int endok=1; | |
| -int line,errors; | |
| +int line,errors=0; | |
| char *multname[]={"","s"}; | |
| void raus(void) | |
| --- vbcc-0.7.orig/doc/vbccz.doc | |
| +++ vbcc-0.7/doc/vbccz.doc | |
| +vbcc - C compiler (c) in 1995-2001 by Volker Barthelmann | |
| + | |
| + | |
| +INTRODUCTION | |
| + | |
| + vbcc is a free portable and retargetable ANSI C compiler. | |
| + It is clearly split into a target independant and a target dependant | |
| + part and supports emulating datatypes of the target machine on any | |
| + other machine so that it is possible to e.g. make a crosscompiler for | |
| + a 64bit machine on a 32bit machine. | |
| + This document only deals with the target dependant parts of the | |
| + Infocom Z-machine code generator. | |
| + | |
| + This is a pre-alpha version! | |
| + | |
| +LEGAL | |
| + | |
| + vbcc is (c) in 1995-99 by Volker Barthelmann. All code is written by me | |
| + and may be freely redistributed as long as no modifications are made | |
| + and nothing is charged for it. | |
| + Non-commercial usage of vbcc is allowed without any restrictions. | |
| + Commercial usage needs my written consent. | |
| + | |
| + Sending me money, gifts, postcards etc. would of course be very nice | |
| + and may encourage further development of vbcc, but is not legally or | |
| + morally necessary to use vbcc. | |
| + | |
| + | |
| + The Z-machine code generator is licensed under the MIT open source license. | |
| + | |
| + Copyright (c) 2001, David Given | |
| + All rights reserved. | |
| + | |
| + Permission is hereby granted, free of charge, to any person obtaining a | |
| + copy of this software and associated documentation files (the "Software"), | |
| + to deal in the Software without restriction, including without limitation | |
| + the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| + and/or sell copies of the Software, and to permit persons to whom the | |
| + Software is furnished to do so, subject to the following conditions: | |
| + | |
| + The above copyright notice and this permission notice shall be included in | |
| + all copies or substantial portions of the Software. | |
| + | |
| + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
| + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
| + DEALINGS IN THE SOFTWARE. | |
| + | |
| + | |
| +ADDITIONAL OPTIONS FOR THIS VERSION | |
| + | |
| + -module-name=<name> | |
| + | |
| + Tells the code generator the C module name to use when emitting | |
| + code. This is used to generate identifiers for statics and | |
| + labels. If a program is made up of multiple modules, each | |
| + module should have a unique name. | |
| + | |
| + If omitted, the compiled module must not be linked with any | |
| + other modules; i.e., omitting the module name is only suitable | |
| + for programs made up of a single source file. In this case the | |
| + BSS initialisation function is called __init_vars(). | |
| + | |
| + -trace-calls | |
| + | |
| + Emit additional code that prints the function name into the | |
| + function prologue. This can be useful for tracing through code. | |
| + | |
| + -trace-all | |
| + | |
| + Emit additional code that prints vbcc's internal representation | |
| + of each instruction before emitting the Z-machine code for that | |
| + instruction. This can be useful for tracing, but is primarily | |
| + used to debug the code generator. | |
| + | |
| + -safe-branches | |
| + | |
| + Attempts to work around an Inform bug that causes relative | |
| + branches in very long source functions to be incorrectly | |
| + generated. (The Z-machine has an upper limit to the offset | |
| + that can be put in a relative branch, but Inform does not test | |
| + for this. If that limit is reached, Inform will happily | |
| + generate incorrect code.) | |
| + | |
| + -comment-ic | |
| + -comment-misc | |
| + | |
| + Emit various comments in the output assembly that shows what | |
| + the code generator is doing. These is completely useless to | |
| + anyone who isn't debugging the code generator. | |
| + | |
| +SOME INTERNALS | |
| + | |
| + This code generator produces files suitable for assembly with the Inform | |
| + Z-machine compiler. | |
| + | |
| + It implements: | |
| + | |
| + 8-bit signed and unsigned chars | |
| + 16-bit signed and unsigned shorts and ints | |
| + 32-bit signed and unsigned longs | |
| + No floating point (may be included at a future date) | |
| + | |
| + 32-bit arithmetic is emulated and may be very slow. | |
| + | |
| + All the standard ANSI C semantics are implemented, or at least should be. | |
| + This includes but is not limited to static data, BSS, stack allocation, | |
| + passing and returning structures to functions, varargs, etc. | |
| + | |
| + The compiled code expects to be linked and run in a particular manner. | |
| + Inform does not use a conventional link stage, which means that certain | |
| + contortions must be done to make the vbcc compiled code to work. A wrapper | |
| + Inform source file is needed that references the vbcc compiled code, sets | |
| + up the BSS, and runs the C. For example, say we have a C source file that | |
| + provides a function main(), called helloworld.c. We would need the following | |
| + Inform file: | |
| + | |
| + #include "/usr/share/vbcc/arch/runtime.s" | |
| + #include "helloworld.o" | |
| + | |
| + [ Initialise; | |
| + __init_vars_helloworld(); | |
| + cinvoke(_main); | |
| + ]; | |
| + | |
| + The C file world be compiled as follows: | |
| + | |
| + vc +z -module-name=helloworld -c helloworld.c | |
| + | |
| + And then the Inform file: | |
| + | |
| + inform helloworld.inf | |
| + | |
| + Each module is provided with a function that sets up that module's BSS. | |
| + This is called __init_vars_<modulename>, and must be called prior to | |
| + running any code in that module. | |
| + | |
| + /usr/share/vbcc/arch/runtime.s is provided with the code generator (if you | |
| + are not using a binary package, it will be in share/vbcc/arch/runtime.s in | |
| + the source directory), and contains helper functions for working around | |
| + Inform bugs, providing extra functionality (the Z-machine has no xor | |
| + instruction), and unsigned and 32-bit arithmetic helper functions. It also | |
| + sets up a 2kB call stack. | |
| + | |
| + The cinvoke() Inform function should be used to call C code from Inform | |
| + code. It sets up the stack and forwards parameters on. The return value of | |
| + the C function is then passed back out of cinvoke(). Note that 32-bit | |
| + parameters are not supported in cinvoke(), and cinvoke() is not reentrant | |
| + (it must not be called from Inform code called from C code called with | |
| + cinvoke()). | |
| + | |
| + No libc is provided with the compiler. If you require a libc, the game | |
| + _Silicon Castles_ comes with an extremely minimalist libc that may be | |
| + useful. | |
| + | |
| + The Z-machine is not implemented as a particularly normal register-based | |
| + processor. As a result, the code generator is a bit odd in places. The | |
| + Z-machine's local variables are used in place of registers. These are | |
| + referred to here as xp and r0..r12. | |
| + | |
| + xp is the C stack pointer. The Z-machine's own stack is not memory mapped | |
| + and so is useless from the C point of view. As a result, the C stack is | |
| + held in main memory; it is set up by the cinvoke() function. It should be | |
| + borne in mind that this means that both stacks will need adjusting for a | |
| + longjmp() implementation. | |
| + | |
| + r0 to r5 are used for parameter passing when calling functions, but at all | |
| + other times all the registers are used for scratch space. The Z-machine | |
| + automatically saves all the locals when making procedure calls, so | |
| + parameters are returned on the Z-machine stack. | |
| + | |
| +STDARG | |
| + | |
| + #ifndef __STDARG_H | |
| + #define __STDARG_H | |
| + | |
| + #ifdef __Z__ | |
| + typedef char* va_list; | |
| + extern va_list __va_start; /* magic */ | |
| + | |
| + #define va_start(ap, lastarg) \ | |
| + ((ap) = __va_start) | |
| + #define va_arg(ap, type) \ | |
| + (((ap) += (sizeof(type)<sizeof(int)) ? sizeof(int) : sizeof(type)), \ | |
| + ((type*)ap)[-1]) | |
| + #define va_end(ap) ((ap) = 0) | |
| + #endif | |
| + | |
| + #endif /* __STDARG_H */ | |
| + | |
| +KNOWN PROBLEMS | |
| + | |
| + I'm sure there are some in the compiler, but nothing's bitten me yet. The | |
| + main problems are caused by the fact that vbcc generates really weird | |
| + Z-machine code that stresses Inform and the interpreters in ways that have | |
| + never been tested before. I've found at least two major interpreter bugs; | |
| + some versions of nitfol think that -32760 > 32760, and some versions of Zip | |
| + think that $FF00 asr 8 != $FFFF. There are some Inform bugs that generate | |
| + bogus code, too. | |
| + | |
| +David Given dg@cowlark.com | |
| + | |
| --- vbcc-0.7.orig/configure.in | |
| +++ vbcc-0.7/configure.in | |
| +# configure.in | |
| +# vbcc for Unix autoconf file | |
| + | |
| +# Check we're in the right directory. | |
| + | |
| +AC_INIT(main.c) | |
| + | |
| +# Check for programs. | |
| + | |
| +AC_PROG_CC | |
| + | |
| +# Check for header files. | |
| + | |
| +AC_HEADER_STDC | |
| + | |
| +# ...and output. | |
| + | |
| +AC_OUTPUT(Makefile) | |
| + | |
| --- vbcc-0.7.orig/Makefile.in | |
| +++ vbcc-0.7/Makefile.in | |
| +# The usual settings. | |
| + | |
| +CC = gcc | |
| +CFLAGS = -O2 -g -fsigned-char | |
| +TARGETDIR= machines/$(TARGET) | |
| +INCLUDES = -I. -Imachines/$(TARGET) | |
| +LIBS = | |
| + | |
| +# These are the available targets. | |
| + | |
| +TARGETS = \ | |
| + alpha \ | |
| + c16x \ | |
| + i386 \ | |
| + m68k \ | |
| + ppc \ | |
| + z | |
| + | |
| +# C file compilation rules. | |
| + | |
| +COMPILE = $(CC) $(CFLAGS) $(INCLUDES) | |
| +%.o: %.c | |
| + $(COMPILE) -c -o $@ $< | |
| + | |
| +# Top-level rules. | |
| + | |
| +all: compilers frontend vcpp | |
| + | |
| +clean: compilers-clean frontend-clean vcpp-clean | |
| + | |
| +# === The front-end ========================================================== | |
| + | |
| +VCOBJS = \ | |
| + frontend/vc.o | |
| + | |
| +bin/vc: $(VCOBJS) | |
| + $(CC) $(LIBS) $(VCOBJS) -o $@ | |
| + | |
| +.PHONY: frontend | |
| +frontend: bin/vc | |
| + | |
| +.PHONY: frontend-clean | |
| +frontend-clean: | |
| + $(RM) $(VCOBJS) | |
| + $(RM) bin/vc | |
| + | |
| +# === The preprocessor ======================================================= | |
| + | |
| +VCPPOBJS = \ | |
| + vcpp/cpp.o \ | |
| + vcpp/eval.o \ | |
| + vcpp/getopt.o \ | |
| + vcpp/hideset.o \ | |
| + vcpp/include.o \ | |
| + vcpp/lex.o \ | |
| + vcpp/macro.o \ | |
| + vcpp/nlist.o \ | |
| + vcpp/tokens.o \ | |
| + vcpp/unix.o | |
| + | |
| +bin/vcpp: $(VCPPOBJS) | |
| + $(CC) $(LIBS) $(VCPPOBJS) -o $@ | |
| + | |
| +.PHONY: vcpp | |
| +vcpp: bin/vcpp | |
| + | |
| +.PHONY: vcpp-clean | |
| +vcpp-clean: | |
| + $(RM) $(VCPPOBJS) | |
| + $(RM) bin/vcpp | |
| + | |
| +# === The compilers ========================================================== | |
| + | |
| +.PHONY: compilers | |
| +compilers: | |
| + for target in $(TARGETS); do \ | |
| + $(MAKE) TARGET=$$target compiler.$$target; \ | |
| + done | |
| + | |
| +.PHONY: compilers-clean | |
| +compilers-clean: dtgen-clean | |
| + for target in $(TARGETS); do \ | |
| + $(MAKE) TARGET=$$target compiler-clean.$$target; \ | |
| + done | |
| + | |
| +# Build the dtgen program. | |
| + | |
| +DTGENOBJECTS = \ | |
| + datatypes/dtgen.o | |
| + | |
| +datatypes/dtgen.o: datatypes/dtgen.c datatypes/datatypes.h datatypes/dtconv.h | |
| + | |
| +dtgen: $(DTGENOBJECTS) | |
| + $(CC) $(DTGENOBJECTS) -o $@ $(LIBS) | |
| + | |
| +.PHONY: dtgen-clean | |
| +dtgen-clean: | |
| + $(RM) dtgen $(DTGENOBJECTS) | |
| + | |
| +# Build a generic compiler. | |
| + | |
| +BOBJECTS = \ | |
| + $(TARGETDIR)/main.o \ | |
| + $(TARGETDIR)/vars.o \ | |
| + $(TARGETDIR)/declaration.o \ | |
| + $(TARGETDIR)/parse_expr.o \ | |
| + $(TARGETDIR)/type_expr.o \ | |
| + $(TARGETDIR)/ic.o \ | |
| + $(TARGETDIR)/machine.o \ | |
| + $(TARGETDIR)/statements.o \ | |
| + $(TARGETDIR)/preproc.o \ | |
| + $(TARGETDIR)/supp.o \ | |
| + $(TARGETDIR)/dt.o | |
| + | |
| +$(TARGETDIR)/main.o: main.c vbc.h supp.h $(TARGETDIR)/machine.h $(TARGETDIR)/dt.h | |
| + $(COMPILE) -c -o $@ $< | |
| +$(TARGETDIR)/vars.o: vars.c vbc.h supp.h $(TARGETDIR)/machine.h errors.h $(TARGETDIR)/dt.h | |
| + $(COMPILE) -c -o $@ $< | |
| +$(TARGETDIR)/declaration.o: declaration.c vbc.h supp.h $(TARGETDIR)/machine.h $(TARGETDIR)/dt.h | |
| + $(COMPILE) -c -o $@ $< | |
| +$(TARGETDIR)/parse_expr.o: parse_expr.c vbc.h supp.h $(TARGETDIR)/machine.h $(TARGETDIR)/dt.h | |
| + $(COMPILE) -c -o $@ $< | |
| +$(TARGETDIR)/type_expr.o: type_expr.c vbc.h supp.h $(TARGETDIR)/machine.h $(TARGETDIR)/dt.h | |
| + $(COMPILE) -c -o $@ $< | |
| +$(TARGETDIR)/ic.o: ic.c vbc.h supp.h $(TARGETDIR)/machine.h $(TARGETDIR)/dt.h | |
| + $(COMPILE) -c -o $@ $< | |
| +$(TARGETDIR)/statements.o: statements.c vbc.h supp.h $(TARGETDIR)/machine.h $(TARGETDIR)/dt.h | |
| + $(COMPILE) -c -o $@ $< | |
| +$(TARGETDIR)/preproc.o: preproc.c vbpp.h supp.h vbc.h $(TARGETDIR)/dt.h | |
| + $(COMPILE) -c -o $@ $< | |
| +$(TARGETDIR)/supp.o: supp.c supp.h $(TARGETDIR)/machine.h $(TARGETDIR)/dt.h | |
| + $(COMPILE) -c -o $@ $< | |
| +$(TARGETDIR)/machine.o: $(TARGETDIR)/machine.c $(TARGETDIR)/dt.h | |
| + $(COMPILE) -c -o $@ $< | |
| +$(TARGETDIR)/dt.o: $(TARGETDIR)/dt.c $(TARGETDIR)/dt.h | |
| + $(COMPILE) -c -o $@ $< -Idatatypes | |
| + | |
| +FOBJECTS = \ | |
| + $(BOBJECTS) \ | |
| + $(TARGETDIR)/opt.o \ | |
| + $(TARGETDIR)/av.o \ | |
| + $(TARGETDIR)/rd.o \ | |
| + $(TARGETDIR)/regs.o \ | |
| + $(TARGETDIR)/flow.o \ | |
| + $(TARGETDIR)/cse.o \ | |
| + $(TARGETDIR)/cp.o \ | |
| + $(TARGETDIR)/loop.o \ | |
| + $(TARGETDIR)/alias.o | |
| + | |
| +$(TARGETDIR)/opt.o: opt.c opt.h supp.h $(TARGETDIR)/machine.h $(TARGETDIR)/dt.h | |
| + $(COMPILE) -c -o $@ $< | |
| +$(TARGETDIR)/av.o: av.c opt.h supp.h $(TARGETDIR)/machine.h $(TARGETDIR)/dt.h | |
| + $(COMPILE) -c -o $@ $< | |
| +$(TARGETDIR)/rd.o: rd.c opt.h supp.h $(TARGETDIR)/machine.h $(TARGETDIR)/dt.h | |
| + $(COMPILE) -c -o $@ $< | |
| +$(TARGETDIR)/regs.o: regs.c opt.h supp.h $(TARGETDIR)/machine.h $(TARGETDIR)/dt.h | |
| + $(COMPILE) -c -o $@ $< | |
| +$(TARGETDIR)/flow.o: flow.c opt.h supp.h $(TARGETDIR)/machine.h $(TARGETDIR)/dt.h | |
| + $(COMPILE) -c -o $@ $< | |
| +$(TARGETDIR)/cse.o: cse.c opt.h supp.h $(TARGETDIR)/machine.h $(TARGETDIR)/dt.h | |
| + $(COMPILE) -c -o $@ $< | |
| +$(TARGETDIR)/cp.o: cp.c opt.h supp.h $(TARGETDIR)/machine.h $(TARGETDIR)/dt.h | |
| + $(COMPILE) -c -o $@ $< | |
| +$(TARGETDIR)/loop.o: loop.c opt.h supp.h $(TARGETDIR)/machine.h $(TARGETDIR)/dt.h | |
| + $(COMPILE) -c -o $@ $< | |
| +$(TARGETDIR)/alias.o: alias.c opt.h supp.h $(TARGETDIR)/machine.h $(TARGETDIR)/dt.h | |
| + $(COMPILE) -c -o $@ $< | |
| + | |
| +$(TARGETDIR)/dt.h: dtgen | |
| + ./dtgen $(TARGETDIR)/machine.dt $(TARGETDIR)/dt.h $(TARGETDIR)/dt.c | |
| + | |
| +bin/vbcc$(TARGET): $(TARGETDIR)/dt.h $(FOBJECTS) | |
| + $(CC) $(FOBJECTS) -o bin/vbcc$(TARGET) $(LIBS) | |
| + | |
| +.PHONY: compiler.$(TARGET) | |
| +compiler.$(TARGET): bin/vbcc$(TARGET) | |
| + | |
| +.PHONY: compiler-clean.$(TARGET) | |
| +compiler-clean.$(TARGET): | |
| + $(RM) $(FOBJECTS) bin/vbcc$(TARGET) | |
| + $(RM) $(TARGETDIR)/dt.h $(TARGETDIR)/dt.c | |
| + | |
| + | |
| --- vbcc-0.7.orig/vbc.h | |
| +++ vbcc-0.7/vbc.h | |
| #endif | |
| struct argument_list{ | |
| - np arg; | |
| - struct argument_list *next; | |
| + np arg; | |
| + struct argument_list *next; | |
| + struct IC *pushic; | |
| }; | |
| extern void gen_IC(np,int,int),convert(np,int),gen_label(int); | |
| extern void savescratch(int,struct IC *,int); | |
| struct regargs_list{ | |
| - struct regargs_list *next; | |
| - int reg; | |
| - struct Var *v; | |
| + struct regargs_list *next; | |
| + struct argument_list *al; | |
| + int reg; | |
| + struct Var *v; | |
| }; | |
| #ifdef HAVE_REGPARMS | |
| -extern zlong push_args(struct argument_list *,struct struct_declaration *,int,struct regargs_list **,struct reg_handle *,struct obj *,int); | |
| +extern zlong push_args(struct argument_list *,struct struct_declaration *,int,struct regargs_list **,struct reg_handle *,struct obj *,struct Typ *,int); | |
| #else | |
| extern zlong push_args(struct argument_list *,struct struct_declaration *,int,struct regargs_list **); | |
| #endif | |
| --- vbcc-0.7.orig/datatypes/dtgen.c | |
| +++ vbcc-0.7/datatypes/dtgen.c | |
| #include <stdio.h> | |
| #include <string.h> | |
| #include <stdlib.h> | |
| +#include <stdint.h> | |
| struct dtlist {char *spec,*descr;} dts[]={ | |
| #include "datatypes.h" | |
| char *nt[TYPECNT+1]; | |
| FILE *fin,*cout,*hout; | |
| int crosscompiler; | |
| +int endian; | |
| void *mymalloc(size_t size) | |
| { | |
| return p; | |
| } | |
| +int getendian(void) | |
| +{ | |
| + union { | |
| + int32_t i; | |
| + int8_t b[4]; | |
| + } u; | |
| + | |
| + u.i = 1; | |
| + return u.b[3] ? 'B' : 'L'; | |
| +} | |
| + | |
| int askyn(void) | |
| { | |
| char in[8]; | |
| cnv[type]=-1; | |
| return 1; | |
| }else{ | |
| - printf("Does your system/compiler support a type implemented as\n%s?\n",dts[i].descr); | |
| - if(askyn()){ | |
| - dt[type]=i; | |
| - nt[type]=asktype(); | |
| - have[i]=type; | |
| - cnv[type]=-1; | |
| + int e = dts[i].descr[0]; | |
| + if ((e == ' ') || (e == endian)) | |
| + { | |
| + dt[type] = i; | |
| + nt[type] = dts[i].descr + 1; | |
| + have[i] = type; | |
| + cnv[type] = -1; | |
| return 1; | |
| }else{ | |
| have[i]=-2; | |
| cnv[type]=j; | |
| return 2; | |
| }else{ | |
| - printf("Does your system/compiler support a type implemented as\n%s?\n",dts[i].descr); | |
| - if(askyn()){ | |
| - dt[type]=i; | |
| - nt[type]=asktype(); | |
| - have[i]=type; | |
| - cnv[type]=j; | |
| + int e = dts[i].descr[0]; | |
| + if ((e == ' ') || (e == endian)) | |
| + { | |
| + dt[type] = i; | |
| + nt[type] = dts[i].descr + 1; | |
| + have[i] = type; | |
| + cnv[type] = j; | |
| return 2; | |
| }else{ | |
| have[i]=-2; | |
| if(!hout){ printf("Could not open <%s> for output!\n",argv[2]);exit(EXIT_FAILURE);} | |
| cout=fopen(argv[3],"w"); | |
| if(!hout){ printf("Could not open <%s> for output!\n",argv[3]);exit(EXIT_FAILURE);} | |
| - printf("Are you building a cross-compiler?\n"); | |
| - crosscompiler=askyn(); | |
| +// printf("Are you building a cross-compiler?\n"); | |
| +// crosscompiler=askyn(); | |
| + crosscompiler = 1; | |
| + endian = getendian(); | |
| for(i=1;i<=TYPECNT;i++){ | |
| fgets(spec,127,fin); | |
| /* printf("Specs for z%s:\n%s\n",typen[i],spec); */ | |
| } | |
| } | |
| fprintf(hout,"\n\n/* Machine generated file. DON'T TOUCH ME! */\n\n\n"); | |
| + fprintf(hout,"#include <stdint.h>\n"); | |
| fprintf(cout,"\n\n/* Machine generated file. DON'T TOUCH ME! */\n\n\n"); | |
| fprintf(cout,"#include \"dt.h\"\n\n"); | |
| for(i=1;i<=TYPECNT;i++){ | |
| --- vbcc-0.7.orig/datatypes/datatypes.h | |
| +++ vbcc-0.7/datatypes/datatypes.h | |
| /* elementary data types currently known to vbcc */ | |
| /* unsigned 8bit byte */ | |
| -"S8BU", "standard unsigned 8bit byte", | |
| +"S8BU", " int8_t", | |
| /* signed 8bit byte */ | |
| -"S8BS", "standard 2-complement 8bit byte", | |
| +"S8BS", " uint8_t", | |
| /* typical unsigned integers, big-endian */ | |
| -"S16BUBE", "standard 8bit-byte-based unsigned 16bit word, big-endian", | |
| -"S32BUBE", "standard 8bit-byte-based unsigned 32bit word, big-endian", | |
| -"S64BUBE", "standard 8bit-byte-based unsigned 64bit byte, big-endian", | |
| +"S16BUBE", "Buint16_t", | |
| +"S32BUBE", "Buint32_t", | |
| +"S64BUBE", "Buint64_t", | |
| /* typical unsigned integers, little-endian */ | |
| -"S16BULE", "standard 8bit-byte-based unsigned 16bit word, little-endian", | |
| -"S32BULE", "standard 8bit-byte-based unsigned 32bit word, little-endian", | |
| -"S64BULE", "standard 8bit-byte-based unsigned 64bit byte, little-endian", | |
| +"S16BULE", "Luint16_t", | |
| +"S32BULE", "Luint32_t", | |
| +"S64BULE", "Luint64_t", | |
| /* typical signed integers, big-endian */ | |
| -"S16BSBE", "standard 8bit-byte-based 2-complement 16bit word, big-endian", | |
| -"S32BSBE", "standard 8bit-byte-based 2-complement 32bit word, big-endian", | |
| -"S64BSBE", "standard 8bit-byte-based 2-complement 64bit word, big-endian", | |
| +"S16BSBE", "Bint16_t", | |
| +"S32BSBE", "Bint32_t", | |
| +"S64BSBE", "Bint64_t", | |
| /* typical signed integers, little-endian */ | |
| -"S16BSLE", "standard 8bit-byte-based 2-complement 16bit word, little-endian", | |
| -"S32BSLE", "standard 8bit-byte-based 2-complement 32bit word, little-endian", | |
| -"S64BSLE", "standard 8bit-byte-based 2-complement 64bit word, little-endian", | |
| +"S16BSLE", "Lint16_t", | |
| +"S32BSLE", "Lint32_t", | |
| +"S64BSLE", "Lint64_t", | |
| /* typical IEEE-floats, big-endian */ | |
| -"S32BIEEEBE", "standard 8bit-byte-based 32bit IEEE floating-point, big-endian", | |
| -"S64BIEEEBE", "standard 8bit-byte-based 64bit IEEE floating-point, big-endian", | |
| +"S32BIEEEBE", "Bfloat", | |
| +"S64BIEEEBE", "Bdouble", | |
| /* typical IEEE-floats, little-endian */ | |
| -"S32BIEEELE", "standard 8bit-byte-based 32bit IEEE floating-point, little-endian", | |
| -"S64BIEEELE", "standard 8bit-byte-based 64bit IEEE floating-point, little-endian", | |
| +"S32BIEEELE", "Lfloat", | |
| +"S64BIEEELE", "Ldouble", | |
Xet Storage Details
- Size:
- 168 kB
- Xet hash:
- 3881531f7312cb51fd38c7a2107658f7bc15c799207b881abc43ca7061836651
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.