summaryrefslogtreecommitdiff
path: root/support/regression/fwk/lib
diff options
context:
space:
mode:
authorXavier ASUS <xavi92psx@gmail.com>2019-10-18 00:31:54 +0200
committerXavier ASUS <xavi92psx@gmail.com>2019-10-18 00:31:54 +0200
commit268a53de823a6750d6256ee1fb1e7707b4b45740 (patch)
tree42c1799a9a82b2f7d9790ee9fe181d72a7274751 /support/regression/fwk/lib
downloadsdcc-gas-268a53de823a6750d6256ee1fb1e7707b4b45740.tar.gz
sdcc-3.9.0 fork implementing GNU assembler syntax
This fork aims to provide better support for stm8-binutils
Diffstat (limited to 'support/regression/fwk/lib')
-rw-r--r--support/regression/fwk/lib/extern1.c28
-rw-r--r--support/regression/fwk/lib/extern2.c9
-rw-r--r--support/regression/fwk/lib/fwk.lib3
-rw-r--r--support/regression/fwk/lib/spec.mk5
-rw-r--r--support/regression/fwk/lib/statics.c42
-rw-r--r--support/regression/fwk/lib/testfwk.c251
-rw-r--r--support/regression/fwk/lib/timeout.c286
7 files changed, 624 insertions, 0 deletions
diff --git a/support/regression/fwk/lib/extern1.c b/support/regression/fwk/lib/extern1.c
new file mode 100644
index 0000000..c397497
--- /dev/null
+++ b/support/regression/fwk/lib/extern1.c
@@ -0,0 +1,28 @@
+/* needed by tests/inline.c */
+
+#ifdef __SDCC
+#pragma std_sdcc99
+#endif
+
+/*--------------
+ bug 2591
+ extern definition with parameters not in registers
+ these parameters should only be allocated here
+ the corresponding inline definition is in tests/inline.c
+*/
+extern long bug_2591 (long a, long b, long c)
+{
+ return a | b | c;
+}
+
+extern char inlined_function (void)
+{
+ return 2;
+}
+
+/* needed by tests/test-p99-conformance.c */
+void
+has_undefined_symbol2(void) {
+ /* empty */
+}
+
diff --git a/support/regression/fwk/lib/extern2.c b/support/regression/fwk/lib/extern2.c
new file mode 100644
index 0000000..3ce738d
--- /dev/null
+++ b/support/regression/fwk/lib/extern2.c
@@ -0,0 +1,9 @@
+/* needed by tests/inline.c */
+
+#ifdef __SDCC
+#pragma std_sdcc99
+#endif
+
+extern char inlined_function (void);
+
+extern char (*inlined_function_pointer) (void) = &inlined_function;
diff --git a/support/regression/fwk/lib/fwk.lib b/support/regression/fwk/lib/fwk.lib
new file mode 100644
index 0000000..20d6224
--- /dev/null
+++ b/support/regression/fwk/lib/fwk.lib
@@ -0,0 +1,3 @@
+statics.rel
+extern1.rel
+extern2.rel
diff --git a/support/regression/fwk/lib/spec.mk b/support/regression/fwk/lib/spec.mk
new file mode 100644
index 0000000..3cc9b86
--- /dev/null
+++ b/support/regression/fwk/lib/spec.mk
@@ -0,0 +1,5 @@
+# Regression test framework library
+
+FWKLIB = $(PORT_CASES_DIR)/statics$(OBJEXT) \
+ $(PORT_CASES_DIR)/extern1$(OBJEXT) \
+ $(PORT_CASES_DIR)/extern2$(OBJEXT)
diff --git a/support/regression/fwk/lib/statics.c b/support/regression/fwk/lib/statics.c
new file mode 100644
index 0000000..55ae9df
--- /dev/null
+++ b/support/regression/fwk/lib/statics.c
@@ -0,0 +1,42 @@
+/* needed by tests/bug1477149.c */
+
+static long long_1 = 1;
+
+static long s_get_long_1(void)
+{
+ long alfa = long_1;
+ long beta = long_1 + alfa;
+ long gamma = long_1 + beta;
+ return alfa + beta + gamma;
+}
+
+long get_long_1(void)
+{
+ return s_get_long_1();
+}
+
+static float float_1 = 1;
+
+static float s_get_float_1(void)
+{
+ float alfa = float_1;
+ float beta = float_1 + alfa;
+ float gamma = float_1 + beta;
+ return alfa + beta + gamma;
+}
+
+float get_float_1(void)
+{
+ return s_get_float_1();
+}
+
+/* for bug 3038028 */
+static char s_get_indexed(char index, char *msg)
+{
+ return msg[index];
+}
+
+char get_indexed(char index, char *msg)
+{
+ return s_get_indexed(index, msg);
+}
diff --git a/support/regression/fwk/lib/testfwk.c b/support/regression/fwk/lib/testfwk.c
new file mode 100644
index 0000000..f8c7a93
--- /dev/null
+++ b/support/regression/fwk/lib/testfwk.c
@@ -0,0 +1,251 @@
+/** Test framework support functions.
+ */
+#include <testfwk.h>
+#ifndef NO_VARARGS
+#include <stdarg.h>
+#endif
+
+#ifdef __SDCC_ds390
+#include <tinibios.h> /* main() must see the ISR declarations */
+#endif
+
+#ifdef __SDCC_mcs51
+/* until changed, isr's must have a prototype in the module containing main */
+void T2_isr (void) __interrupt 5;
+#define MEMSPACE_BUF __idata
+#else
+#define MEMSPACE_BUF
+#endif
+
+/** Define this if the port's div or mod functions are broken.
+ A slow loop based method will be substituded.
+*/
+//#define BROKEN_DIV_MOD 1
+
+extern void _putchar(char c);
+extern void _initEmu(void);
+extern void _exitEmu(void);
+
+int __numTests = 0;
+static int __numFailures = 0;
+
+#if BROKEN_DIV_MOD
+static int
+__div(int num, int denom)
+{
+ int q = 0;
+ while (num >= denom)
+ {
+ q++;
+ num -= denom;
+ }
+ return q;
+}
+
+static int
+__mod (int num, int denom)
+{
+ while (num >= denom)
+ {
+ num -= denom;
+ }
+ return num;
+}
+#else
+#define __div(num, denom) ((num) / (denom))
+#define __mod(num, denom) ((num) % (denom))
+#endif
+
+void
+__prints (const char *s)
+{
+ char c;
+
+ while ('\0' != (c = *s))
+ {
+ _putchar(c);
+ ++s;
+ }
+}
+
+void
+__printd (int n)
+{
+ if (0 == n)
+ {
+ _putchar('0');
+ }
+ else
+ {
+ static char MEMSPACE_BUF buf[6];
+ char MEMSPACE_BUF *p = &buf[sizeof (buf) - 1];
+ char neg = 0;
+
+ buf[sizeof(buf) - 1] = '\0';
+
+ if (0 > n)
+ {
+ n = -n;
+ neg = 1;
+ }
+
+ while (0 != n)
+ {
+ *--p = '0' + __mod (n, 10);
+ n = __div (n, 10);
+ }
+
+ if (neg)
+ _putchar('-');
+
+ __prints(p);
+ }
+}
+
+void
+__printu (unsigned int n)
+{
+ if (0 == n)
+ {
+ _putchar('0');
+ }
+ else
+ {
+ static char MEMSPACE_BUF buf[6];
+ char MEMSPACE_BUF *p = &buf[sizeof (buf) - 1];
+
+ buf[sizeof(buf) - 1] = '\0';
+
+ while (0 != n)
+ {
+ *--p = '0' + __mod (n, 10);
+ n = __div (n, 10);
+ }
+
+ __prints(p);
+ }
+}
+
+#ifndef NO_VARARGS
+void
+__printf (const char *szFormat, ...)
+{
+ va_list ap;
+ va_start (ap, szFormat);
+
+ while (*szFormat)
+ {
+ if (*szFormat == '%')
+ {
+ switch (*++szFormat)
+ {
+ case 's':
+ {
+ char *sz = va_arg (ap, char *);
+ __prints(sz);
+ break;
+ }
+
+ case 'd':
+ {
+ int i = va_arg (ap, int);
+ __printd (i);
+ break;
+ }
+
+ case 'u':
+ {
+ unsigned int i = va_arg (ap, unsigned int);
+ __printu (i);
+ break;
+ }
+
+ case '%':
+ _putchar ('%');
+ break;
+
+ default:
+ break;
+ }
+ }
+ else
+ {
+ _putchar (*szFormat);
+ }
+ szFormat++;
+ }
+ va_end (ap);
+}
+
+void
+__fail (__code const char *szMsg, __code const char *szCond, __code const char *szFile, int line)
+{
+ __printf("--- FAIL: \"%s\" on %s at %s:%u\n", szMsg, szCond, szFile, line);
+ __numFailures++;
+}
+
+int
+main (void)
+{
+ _initEmu();
+
+ __printf("--- Running: %s\n", __getSuiteName());
+
+ __runSuite();
+
+ __printf("--- Summary: %u/%u/%u: %u failed of %u tests in %u cases.\n",
+ __numFailures, __numTests, __numCases,
+ __numFailures, __numTests, __numCases
+ );
+
+ _exitEmu();
+
+ return 0;
+}
+#else
+void
+__fail (__code const char *szMsg, __code const char *szCond, __code const char *szFile, int line)
+{
+ __prints("--- FAIL: \"");
+ __prints(szMsg);
+ __prints("\" on ");
+ __prints(szCond);
+ __prints(" at ");
+ __prints(szFile);
+ _putchar(':');
+ __printd(line);
+ _putchar('\n');
+
+ __numFailures++;
+}
+
+int
+main (void)
+{
+ _initEmu();
+
+ __prints("--- Running: ");
+ __prints(__getSuiteName());
+ _putchar('\n');
+
+ __runSuite();
+
+ __prints("--- Summary: ");
+ __printd(__numFailures);
+ _putchar('/');
+ __printd(__numTests);
+ _putchar('/');
+ __printd(__numCases);
+ __prints(": ");
+ __printd(__numFailures);
+ __prints(" failed of ");
+ __printd(__numTests);
+ __prints(" tests in ");
+ __printd(__numCases);
+ __prints(" cases.\n");
+
+ _exitEmu();
+
+ return 0;
+}
+#endif
diff --git a/support/regression/fwk/lib/timeout.c b/support/regression/fwk/lib/timeout.c
new file mode 100644
index 0000000..85c5600
--- /dev/null
+++ b/support/regression/fwk/lib/timeout.c
@@ -0,0 +1,286 @@
+/*-------------------------------------------------------------------------
+ timeout.c - source file for running ucSim within the regression tests
+
+ Written By - Bernhard Held . bernhard@bernhardheld.de (2001)
+ Native WIN32 port by - Borut Razem . borut.razem@siol.net (2007)
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ In other words, you are welcome to use, share and improve this program.
+ You are forbidden to forbid anyone else to use, share and improve
+ what you give them. Help stamp out software-hoarding!
+-------------------------------------------------------------------------*/
+
+#define PROGNAME "timeout"
+
+#define USAGE PROGNAME " : 1.10\n" \
+ "Usage : " PROGNAME " timeout_in_seconds filename [arguments]\n" \
+ " \"filename\" is executed, the arguments are passed to \"filename\".\n" \
+ " When \"filename\" exits before the timeout expires, the\n" \
+ " exit-status of \"filename\" is returned.\n" \
+ " When the timeout expires before \"filename\" exits, \"filename\"\n" \
+ " will be killed and an exit-status of 1 is returned.\n"
+
+#ifdef _WIN32
+#include <windows.h>
+#include <stdio.h>
+#include <malloc.h>
+
+/*
+ Native WIN32 version:
+
+ The program creates a chile process using CreateProcess(). The waits until:
+ - the child exits
+ The exit status of the child is returned.
+ - the timeout elapses
+ The child will be killed.
+*/
+
+int
+makeCmdLine(char *buf, int argc, const char * const *argv)
+{
+ int len = 0;
+
+ argv += 2;
+ while (argc-- > 2)
+ {
+ int argLen = strlen(*argv);
+ len += argLen;
+ if (buf)
+ {
+ memcpy(buf, *argv, argLen);
+ buf += argLen;
+ }
+ if (argc > 2)
+ {
+ ++len;
+ if (buf)
+ *buf++ = ' ';
+ }
+ ++argv;
+ }
+ if (buf)
+ *buf = '\0';
+
+ return len + 1;
+}
+
+int
+main (int argc, const char * const *argv)
+{
+ STARTUPINFO si;
+ PROCESS_INFORMATION pi;
+ char *cmdLine;
+ long timeout;
+ DWORD exitCode;
+ HANDLE oldStderr;
+
+ if (argc < 3)
+ {
+ fprintf (stderr, USAGE);
+ return 1;
+ }
+ timeout = atol (argv[1]);
+ if (timeout == 0)
+ {
+ fprintf (stderr, "Error parameter " PROGNAME ": must be a non-zero dezimal value\n");
+ return 1;
+ }
+
+ cmdLine = alloca(makeCmdLine(NULL, argc, argv));
+ makeCmdLine(cmdLine, argc, argv);
+
+ ZeroMemory(&si, sizeof (si));
+ si.cb = sizeof (si);
+ ZeroMemory(&pi, sizeof (pi));
+
+ /* We'll redirect here stderr to stdout, which will be redirected */
+ /* to /dev/null by the shell. The shell could also redirect stderr */
+ /* to /dev/null, but then this program doesn't have the chance to */
+ /* output any real error. */
+ oldStderr = GetStdHandle (STD_ERROR_HANDLE);
+ SetStdHandle (STD_ERROR_HANDLE, GetStdHandle (STD_OUTPUT_HANDLE));
+
+ /* Start the child process. */
+ if(!CreateProcess (NULL, // No module name (use command line)
+ cmdLine, // Command line
+ NULL, // Process handle not inheritable
+ NULL, // Thread handle not inheritable
+ TRUE, // Set handle inheritance to TRUE
+ 0, // No creation flags
+ NULL, // Use parent's environment block
+ NULL, // Use parent's starting directory
+ &si, // Pointer to STARTUPINFO structure
+ &pi) // Pointer to PROCESS_INFORMATION structure
+ )
+ {
+ printf ("CreateProcess failed (%d).\n", GetLastError ());
+ return 1;
+ }
+
+ /* Restore stderr */
+ SetStdHandle (STD_ERROR_HANDLE, oldStderr);
+
+ /* Wait until child process exits or timeout expires. */
+ if (WaitForSingleObject (pi.hProcess, timeout * 1000) == WAIT_TIMEOUT)
+ {
+ TerminateProcess (pi.hProcess, 1);
+ WaitForSingleObject (pi.hProcess, INFINITE);
+ }
+
+ GetExitCodeProcess (pi.hProcess, &exitCode);
+
+ /* Close process and thread handles. */
+ CloseHandle (pi.hProcess);
+ CloseHandle (pi.hThread);
+
+ return exitCode;
+}
+
+#else
+
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/wait.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <unistd.h>
+
+/* First the program tries to limit the maximum CPU-time to the timeout-value.
+ Then the child is run with execvp().
+
+ It's not possible to limit the CPU-time under Cygwin (V1.3.3). If setrlimit (RLIMIT_CPU, rlp)
+ fails, the program will fork() and run the child with execvp(). The fork/exec pair is slow on
+ Cygwin, but what else can we do? The parent sleeps until:
+ - a signal shows the childīs exitus
+ The exit status of the child is returned.
+ - the timeout elapses
+ The child will be killed.
+*/
+
+/* Get the status from all child processes that have terminated, without ever waiting.
+ This function is designed to be a handler for SIGCHLD, the signal that indicates
+ that at least one child process has terminated.
+ http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_23.html#SEC401
+*/
+
+#ifndef WAIT_ANY
+ #define WAIT_ANY -1
+#endif
+
+void
+sigchld_handler (int signum)
+{
+ int pid;
+ int status;
+ int exit_status = 0;
+
+ while (1)
+ {
+ pid = waitpid (WAIT_ANY, &status, WNOHANG);
+ if (WEXITSTATUS (status))
+ exit_status = 1; // WEXITSTATUS(status);
+ /* pid == -1: no children */
+ /* pid == 0: no children to be noticed */
+ if (pid <= 0)
+ break;
+ }
+ exit (exit_status);
+}
+
+int
+main (int argc, char * const *argv)
+{
+ /* if getrlimit() / setrlimit() succeed, then no fork is neeeded */
+ int flagNoFork = 0;
+ int old_stderr;
+ long timeout;
+ pid_t pid_child;
+ struct rlimit rl;
+
+ if (argc < 3)
+ {
+ fprintf (stderr, USAGE);
+ return 1;
+ }
+ timeout = atol (argv[1]);
+ if (timeout == 0)
+ {
+ fprintf (stderr, "Error parameter " PROGNAME ": must be a non-zero dezimal value\n");
+ return 1;
+ }
+
+ /* try to use getrlimit() / setrlimit() for RLIMIT_CPU */
+ /* to limit the CPU-time */
+ if (getrlimit (RLIMIT_CPU, &rl) == 0)
+ {
+ rl.rlim_cur = timeout;
+ if (setrlimit (RLIMIT_CPU, &rl) == 0)
+ flagNoFork = 1;
+ }
+
+ if (flagNoFork)
+ { /* the CPU-time is limited: simple execvp */
+
+ /* s51 prints warnings on stderr: */
+ /* serial input/output interface connected to a non-terminal file. */
+ /* We'll redirect here stderr to stdout, which will be redirected */
+ /* to /dev/null by the shell. The shell could also redirect stderr */
+ /* to /dev/null, but then this program doesn't have the chance to */
+ /* output any real error. */
+ old_stderr = dup (STDERR_FILENO);
+ dup2 (STDOUT_FILENO, STDERR_FILENO);
+ /* shouldn't return */
+ execvp (argv[2], argv + 2);
+ /* restore stderr */
+ dup2 (old_stderr, STDERR_FILENO);
+ perror (argv[2]);
+ return 1; /* Error */
+ }
+ else
+ {
+ /* do it the hard way: fork/exec */
+ signal (SIGCHLD, sigchld_handler);
+ pid_child = fork();
+ if (pid_child == 0)
+ {
+ /* s51 prints warnings on stderr: */
+ /* serial input/output interface connected to a non-terminal file. */
+ /* We'll redirect here stderr to stdout, which will be redirected */
+ /* to /dev/null by the shell. The shell could also redirect stderr */
+ /* to /dev/null, but then this program doesn't have the chance to */
+ /* output any real error. */
+ old_stderr = dup (STDERR_FILENO);
+ dup2 (STDOUT_FILENO, STDERR_FILENO);
+ /* shouldn't return */
+ execvp (argv[2], argv + 2);
+ /* restore stderr */
+ dup2 (old_stderr, STDERR_FILENO);
+ perror (argv[2]);
+ return 1; /* Error */
+ }
+ else
+ {
+ /* this timeout is hopefully aborted by a SIGCHLD */
+ sleep (timeout);
+ fprintf (stderr, PROGNAME ": timeout, killing child %s\n", argv[2]);
+ kill (pid_child, SIGTERM);
+ return 1; /* Error */
+ }
+ }
+}
+#endif