aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Stallman <rms@gnu.org>1992-08-20 19:33:41 +0000
committerRichard Stallman <rms@gnu.org>1992-08-20 19:33:41 +0000
commitebea352be590cd4d63acd2e68a9c5b3153473021 (patch)
tree08b7c4aa48a62972504b65540ae0d7a869e81449 /gcc
parent5ac3f0f448487f214429f35fb6880991214fbfe2 (diff)
downloadgcc-ebea352be590cd4d63acd2e68a9c5b3153473021.zip
gcc-ebea352be590cd4d63acd2e68a9c5b3153473021.tar.gz
gcc-ebea352be590cd4d63acd2e68a9c5b3153473021.tar.bz2
(not_qsort): New function.
From-SVN: r1914
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/vax/vax.c89
1 files changed, 89 insertions, 0 deletions
diff --git a/gcc/config/vax/vax.c b/gcc/config/vax/vax.c
index 6ca2ec1..14f98e4 100644
--- a/gcc/config/vax/vax.c
+++ b/gcc/config/vax/vax.c
@@ -577,3 +577,92 @@ vax_rtx_cost (x)
}
return c;
}
+
+#ifdef VMS
+/* Additional support code for VMS. */
+
+#ifdef QSORT_WORKAROUND
+ /*
+ Do not use VAXCRTL's qsort() due to a severe bug: once you've
+ sorted something which has a size that's an exact multiple of 4
+ and is longword aligned, you cannot safely sort anything which
+ is either not a multiple of 4 in size or not longword aligned.
+ A static "move-by-longword" optimization flag inside qsort() is
+ never reset. This is known of affect VMS V4.6 through VMS V5.5-1.
+
+ In this work-around an insertion sort is used for simplicity.
+ The qsort code from glibc should probably be used instead.
+ */
+void
+not_qsort (array, count, size, compare)
+ void *array;
+ unsigned count, size;
+ int (*compare)();
+{
+
+ if (size == sizeof (short))
+ {
+ register int i;
+ register short *next, *prev;
+ short tmp, *base = array;
+
+ for (next = base, i = count - 1; i > 0; i--)
+ {
+ prev = next++;
+ if ((*compare)(next, prev) < 0)
+ {
+ tmp = *next;
+ do *(prev + 1) = *prev;
+ while (--prev >= base ? (*compare)(&tmp, prev) < 0 : 0);
+ *(prev + 1) = tmp;
+ }
+ }
+ }
+ else if (size == sizeof (long))
+ {
+ register int i;
+ register long *next, *prev;
+ long tmp, *base = array;
+
+ for (next = base, i = count - 1; i > 0; i--)
+ {
+ prev = next++;
+ if ((*compare)(next, prev) < 0)
+ {
+ tmp = *next;
+ do *(prev + 1) = *prev;
+ while (--prev >= base ? (*compare)(&tmp, prev) < 0 : 0);
+ *(prev + 1) = tmp;
+ }
+ }
+ }
+ else /* arbitrary size */
+ {
+#ifdef USE_C_ALLOCA
+ extern void *alloca ();
+#endif
+ register int i;
+ register char *next, *prev, *tmp = alloca (size), *base = array;
+
+ for (next = base, i = count - 1; i > 0; i--)
+ { /* count-1 forward iterations */
+ prev = next, next += size; /* increment front pointer */
+ if ((*compare)(next, prev) < 0)
+ { /* found element out of order; move others up then re-insert */
+ memcpy (tmp, next, size); /* save smaller element */
+ do { memcpy (prev + size, prev, size); /* move larger elem. up */
+ prev -= size; /* decrement back pointer */
+ } while (prev >= base ? (*compare)(tmp, prev) < 0 : 0);
+ memcpy (prev + size, tmp, size); /* restore small element */
+ }
+ }
+#ifdef USE_C_ALLOCA
+ alloca (0);
+#endif
+ }
+
+ return;
+}
+#endif /* QSORT_WORKAROUND */
+
+#endif /* VMS */