chip@tct.uucp (Chip Salzenberg) (02/15/91)
[ AUTHOR'S NOTE: A few days ago, I posted an earlier version of these patches. Those patches worked, except that "#pragma pack" was broken -- and that was one of the primary motivations for the patches! As to why I didn't test it before posting, I can only plead temporary insanity. I apologize for the inconvenience. Those of you who applied the previous patches, all you really need is the two changes to stor-layout.c that mention the macro PCC_BITFIELD_TYPE_MATTERS. This entirely repackaged set of patches has been carefully tested using the enclosed "packtest" program, and it looks okay. But, as always, your mileage may vary. Shar and enjoy. ] The enclosed patches are a port of GCC 1.39 to SCO UNIX. I appreciate RMS's addition of a SCO configuration file and other patches to GCC 1.39. However, there were a few things overlooked which are addressed herein, such as STRUCT_RETURN_CALLER_POP in tm-i386sco.h. Also, RMS isn't going to add the Microsloth "#pragma pack()" to mainstream GCC, so it is still a custom add-on. (GCC 2.0 will have a keyword to indicate packing, so all is not lost. :-)) NON-SCO USERS: You will be interested in the patch to stmt.c; it is the GCC side of a G++ bug fix. I think that the two patches to stor-layout.c that mention PCC_BITFIELD_TYPE_MATTERS fix a GCC bug (the test for "this field is a bitfield" was too lax), but I would expect such a bug to make all structures at least sizeof(int) in size, and I haven't seen that symptom. But the fix _is_ necessary for #pragma pack to work. NON-SCO USERS OF SYSTEM V: You will want to use the patch to symout.c to use getcwd() instead of getwd(). SCO USERS: At the end of the patches is a sharchive containing three files you'll need to build GCC: Makefile-diffs Diffs for my Makefile; uses "rcc". pragma.c Support for structure packing ("#pragma pack"). packtest.c Regression test for "#pragma pack". Thanks again to Steve Bleazard for the original "#pragma pack" support, done for a Xenix/386 port: he's a brave man. And, of course, thanks to RMS for an excellent compiler. Index: tm-i386sco.h *************** *** 17,21 **** #undef LIB_SPEC #define LIB_SPEC \ ! "%{p:-L/usr/lib/libp}%{pg:-L/usr/lib/libp} libintl.a%s -lc" /* Specify predefined symbols in preprocessor. */ --- 17,21 ---- #undef LIB_SPEC #define LIB_SPEC \ ! "%{p:-L/usr/lib/libp}%{pg:-L/usr/lib/libp} -lintl -lc" /* Specify predefined symbols in preprocessor. */ *************** *** 31,32 **** --- 31,43 ---- #define NO_DOLLAR_IN_LABEL + + /* SCO's libraries are compiled with Microsoft C, which requires the + caller to pop the extra argument passed to functions that return + structures. */ + + #define STRUCT_RETURN_CALLER_POP + + /* SCO's use of Microsoft C requires us to support #pragma pack(), + which controls structure packing, until GCC 2.0 is released. */ + + #define PRAGMA_PACK Index: gcc.c *************** *** 300,304 **** %{A} %{d} %{e*} %{N} %{n} %{r} %{s} %{S} %{T*} %{t} %{u*} %{X} %{x} %{z}\ %{y*} %{!A:%{!nostdlib:%S}} \ ! %{L*} %o %{!nostdlib:gnulib%s %{g:-lg} %L gnulib%s %{!A:%E}}\n }}}}"; /* Accumulate a command (program name and args), and run it. */ --- 300,304 ---- %{A} %{d} %{e*} %{N} %{n} %{r} %{s} %{S} %{T*} %{t} %{u*} %{X} %{x} %{z}\ %{y*} %{!A:%{!nostdlib:%S}} \ ! %{L*} -L%A %o %{!nostdlib:%{g:-lg} gnulib%s %L gnulib%s %{!A:%E}}\n }}}}"; /* Accumulate a command (program name and args), and run it. */ *************** *** 1199,1202 **** --- 1199,1207 ---- case 0: fatal ("Invalid specification! Bug in cc."); + + case 'A': + obstack_grow (&obstack, standard_startfile_prefix, + strlen (standard_startfile_prefix)); + break; case 'b': Index: stmt.c *************** *** 1429,1432 **** --- 1429,1437 ---- block = block->next; + /* Only use `last_insn' if there are cleanups which must be run. */ + + if (block || cleanup_label != 0) + last_insn = get_last_insn (); + /* If yes, use a goto to return, since that runs cleanups. */ Index: stor-layout.c *************** *** 499,502 **** --- 499,506 ---- layout_decl (field, var_size ? size_unit : const_size); + #ifdef PRAGMA_PACK + if (pragma_pack_seen()) + DECL_ALIGN(field) = MIN(pragma_align_val(), DECL_ALIGN(field)); + #endif desired_align = DECL_ALIGN (field); *************** *** 509,513 **** /* In PCC on Vax, Sony, etc., a bit field of declare type `int' forces the entire structure to have `int' alignment. */ ! if (PCC_BITFIELD_TYPE_MATTERS && DECL_NAME (field) != 0) record_align = MAX (record_align, TYPE_ALIGN (TREE_TYPE (field))); #endif --- 513,518 ---- /* In PCC on Vax, Sony, etc., a bit field of declare type `int' forces the entire structure to have `int' alignment. */ ! if (PCC_BITFIELD_TYPE_MATTERS && TREE_PACKED (field) ! && TREE_TYPE (field) != error_mark_node) record_align = MAX (record_align, TYPE_ALIGN (TREE_TYPE (field))); #endif *************** *** 540,544 **** #ifdef PCC_BITFIELD_TYPE_MATTERS ! if (PCC_BITFIELD_TYPE_MATTERS && TREE_CODE (field) == FIELD_DECL && TREE_TYPE (field) != error_mark_node) { --- 545,549 ---- #ifdef PCC_BITFIELD_TYPE_MATTERS ! if (PCC_BITFIELD_TYPE_MATTERS && TREE_PACKED (field) && TREE_TYPE (field) != error_mark_node) { Index: symout.c *************** *** 1243,1247 **** buffer.filedir = (char *) next_address; #ifdef USG ! strcpy (dir, getcwd (dir, MAXNAMLEN)); #else #ifndef VMS --- 1243,1251 ---- buffer.filedir = (char *) next_address; #ifdef USG ! { ! extern char *getcwd(); ! if (getcwd (dir, MAXNAMLEN) == 0) ! strcpy (dir, "."); ! } #else #ifndef VMS Index: version.c *************** *** 1 **** ! char *version_string = "1.39"; --- 1,9 ---- ! #include "config.h" ! ! char *version_string = ! #ifdef PRAGMA_PACK ! "1.39 (#pragma pack)" ! #else ! "1.39" ! #endif ! ; Index: c-parse.y *************** *** 1794,1799 **** && getc (finput) == 'm' && getc (finput) == 'a' ! && ((c = getc (finput)) == ' ' || c == '\t' || c == '\n')) goto skipline; } --- 1794,1843 ---- && getc (finput) == 'm' && getc (finput) == 'a' ! && ((c = getc (finput)) == ' ' || c == '\t')) ! { ! #ifdef PRAGMA_PACK ! int i; ! ! while ((c = getc (finput)) == ' ' || c == '\t') ! ; ! ungetc (c, finput); ! for (i = 0; i < 32; ++i) /* arbitrary pragma directive size */ ! { ! if ((c = getc (finput)) < 'a' || c > 'z') ! { ! ungetc (c, finput); ! break; ! } ! token_buffer[i] = c; ! } ! token_buffer[i] = '\0'; ! ! if (strcmp(token_buffer, "pack") != 0) ! goto skipline; ! ! if ((c = getc (finput)) != '(') ! { ! ungetc (c, finput); ! error ("invalid #pragma pack"); ! goto skipline; ! } ! ! if ((c = getc (finput)) == '1' || c == '2' || c == '4') ! { ! pragma_pack (c - '0'); ! c = getc (finput); ! } ! else ! pragma_pack_default (); ! ! if (c != ')') ! { ! ungetc (c, finput); ! error ("invalid #pragma pack"); ! goto skipline; ! } ! #endif goto skipline; + } } Index: c-parse.tab.c *************** *** 750,753 **** --- 750,754 ---- #ifdef __GNUC__ + #undef alloca #define alloca __builtin_alloca #else /* Not GNU C. */ *************** *** 3023,3028 **** && getc (finput) == 'm' && getc (finput) == 'a' ! && ((c = getc (finput)) == ' ' || c == '\t' || c == '\n')) goto skipline; } --- 3024,3073 ---- && getc (finput) == 'm' && getc (finput) == 'a' ! && ((c = getc (finput)) == ' ' || c == '\t')) ! { ! #ifdef PRAGMA_PACK ! int i; ! ! while ((c = getc (finput)) == ' ' || c == '\t') ! ; ! ungetc (c, finput); ! for (i = 0; i < 32; ++i) /* arbitrary pragma directive size */ ! { ! if ((c = getc (finput)) < 'a' || c > 'z') ! { ! ungetc (c, finput); ! break; ! } ! token_buffer[i] = c; ! } ! token_buffer[i] = '\0'; ! ! if (strcmp(token_buffer, "pack") != 0) ! goto skipline; ! ! if ((c = getc (finput)) != '(') ! { ! ungetc (c, finput); ! error ("invalid #pragma pack"); ! goto skipline; ! } ! ! if ((c = getc (finput)) == '1' || c == '2' || c == '4') ! { ! pragma_pack (c - '0'); ! c = getc (finput); ! } ! else ! pragma_pack_default (); ! ! if (c != ')') ! { ! ungetc (c, finput); ! error ("invalid #pragma pack"); ! goto skipline; ! } ! #endif goto skipline; + } } //////////////////////// // NEW FILES FOLLOW // //////////////////////// #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of shell archive." # Contents: Makefile-diffs pragma.c packtest.c # Wrapped by chip@tct on Thu Feb 14 11:19:21 1991 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'Makefile-diffs' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Makefile-diffs'\" else echo shar: Extracting \"'Makefile-diffs'\" \(3344 characters\) sed "s/^X//" >'Makefile-diffs' <<'END_OF_FILE' XIndex: Makefile X*************** X*** 22,26 **** X # See below for how to change them for certain systems. X X! CFLAGS = -g $(XCFLAGS) X CC = cc X BISON = bison X--- 22,26 ---- X # See below for how to change them for certain systems. X X! CFLAGS = -O $(XCFLAGS) X CC = cc X BISON = bison X*************** X*** 50,54 **** X X # CFLAGS for use with OLDCC, for compiling hard-params. X! HARD_PARAMS_FLAGS= X X # Directory where sources are, from where we are. X--- 50,54 ---- X X # CFLAGS for use with OLDCC, for compiling hard-params. X! HARD_PARAMS_FLAGS= $(RCCFLAGS) X X # Directory where sources are, from where we are. X*************** X*** 55,65 **** X srcdir = . X # Directory in which to put the executable for the command `gcc' X! bindir = $(prefix)/usr/local/bin X # Directory in which to put the subprograms used by the compiler. X! libdir = $(prefix)/usr/local/lib X # Directory in which to put man pages. X! mandir = $(prefix)/usr/local/man/man1 X # Number to put in man-page filename. X! manext = 1 X X # Additional system libraries to link with. X--- 55,65 ---- X srcdir = . X # Directory in which to put the executable for the command `gcc' X! bindir = $(prefix)/u/local/bin X # Directory in which to put the subprograms used by the compiler. X! libdir = $(prefix)/u/local/lib X # Directory in which to put man pages. X! mandir = $(prefix)/u/local/man/man.C X # Number to put in man-page filename. X! manext = C X X # Additional system libraries to link with. X*************** X*** 105,111 **** X # You might also want to remove limits.h from the definition of USER_H, X # since the one that comes with the system is good for POSIX. X! # RANLIB = : X! # CC = rcc X! # OLDCC = rcc X X # On a 386 running an ISC system, uncomment the following lines. X--- 105,115 ---- X # You might also want to remove limits.h from the definition of USER_H, X # since the one that comes with the system is good for POSIX. X! RANLIB = : X! CC = rcc X! OLDCC = rcc X! RCCFLAGS = -Dunix -Di386 -DM_UNIX -DM_I386 X! # Uncomment the following lines if CC is rcc. X! XCFLAGS = $(RCCFLAGS) X! CLIB = -lPW X X # On a 386 running an ISC system, uncomment the following lines. X*************** X*** 193,197 **** X integrate.o jump.o cse.o loop.o flow.o stupid.o combine.o \ X regclass.o local-alloc.o global-alloc.o reload.o reload1.o caller-save.o \ X! insn-peep.o final.o recog.o insn-recog.o insn-extract.o insn-output.o X X # Files to be copied away after each stage in building. X--- 197,202 ---- X integrate.o jump.o cse.o loop.o flow.o stupid.o combine.o \ X regclass.o local-alloc.o global-alloc.o reload.o reload1.o caller-save.o \ X! insn-peep.o final.o recog.o insn-recog.o insn-extract.o insn-output.o \ X! pragma.o X X # Files to be copied away after each stage in building. X*************** X*** 218,223 **** X X # Header files that are made available to programs compiled with gcc. X USER_H = stddef.h assert.h va-i860.h va-mips.h va-pyr.h va-sparc.h \ X! va-spur.h limits.h proto.h X X # The files that "belong" in CONFIG_H are deliberately omitted X--- 223,229 ---- X X # Header files that are made available to programs compiled with gcc. X+ # FOR SCO UNIX: limits.h has been removed X USER_H = stddef.h assert.h va-i860.h va-mips.h va-pyr.h va-sparc.h \ X! va-spur.h proto.h # limits.h X X # The files that "belong" in CONFIG_H are deliberately omitted END_OF_FILE if test 3344 -ne `wc -c <'Makefile-diffs'`; then echo shar: \"'Makefile-diffs'\" unpacked with wrong size! fi # end of 'Makefile-diffs' fi if test -f 'pragma.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'pragma.c'\" else echo shar: Extracting \"'pragma.c'\" \(287 characters\) sed "s/^X//" >'pragma.c' <<'END_OF_FILE' X/* X * Support for Microsloth "#pragma pack(n)" directive. X */ X Xstatic int pack_align = 0; X Xpragma_pack(val) Xint val; X{ X pack_align = 8 * val; X} X Xpragma_align_val() X{ X return pack_align; X} X Xpragma_pack_default() X{ X pack_align = 0; X} X Xint pragma_pack_seen() X{ X return (pack_align != 0); X} END_OF_FILE if test 287 -ne `wc -c <'pragma.c'`; then echo shar: \"'pragma.c'\" unpacked with wrong size! fi # end of 'pragma.c' fi if test -f 'packtest.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'packtest.c'\" else echo shar: Extracting \"'packtest.c'\" \(2439 characters\) sed "s/^X//" >'packtest.c' <<'END_OF_FILE' Xstatic char *rcsid = "@(#)$Header: /pdsrc/Local/RCS/packtest.c,v 1.1 90/04/26 17:50:35 root Exp $"; X X/* X * Regression test to check that gcc's #pragma pack() support does the X * same thing as Microsoft C's. X * X * Run with this command from sh, not csh, since SCO's csh is BROKEN. X * cc packtest.c && ./a.out > m && gcc packtest.c && ./a.out > g && diff m g X * You should not see any output. X * X * $Log: packtest.c,v $ X * Revision 1.1 90/04/26 17:50:35 root X * Initial revision X * X */ X X#pragma pack(4) Xstruct s1 { X char one; X int two; X long three; X double four; X} s1; X#pragma pack(2) Xstruct s2 { X char one; X int two; X long three; X double four; X} s2; X#pragma pack(1) Xstruct s3 { X char one; X int two; X long three; X double four; X} s3; X#pragma pack() Xstruct s4 { X char one; X int two; X long three; X double four; X} s4; Xstruct biggie { X struct s3 x1; X struct s1 b1; X struct s3 x2; X struct s2 b2; X struct s3 x3; X struct s3 b3; X struct s3 x4; X struct s4 b4; X} b; X#define offsetof(TYPE, MEMBER) ((unsigned) &((TYPE *)0)->MEMBER) Xmain() X{ X printf("% 4d% 4d% 4d\n", X offsetof(struct s1, two), X offsetof(struct s1, three), X offsetof(struct s1, four)); X printf("% 4d% 4d% 4d\n", X offsetof(struct s2, two), X offsetof(struct s2, three), X offsetof(struct s2, four)); X printf("% 4d% 4d% 4d\n", X offsetof(struct s3, two), X offsetof(struct s3, three), X offsetof(struct s3, four)); X printf("% 4d% 4d% 4d\n", X offsetof(struct s4, two), X offsetof(struct s4, three), X offsetof(struct s4, four)); X printf("\n% 4d% 4d% 4d\n", X ((char *)&b.b1.two) - ((char *)&b.b1.one), X ((char *)&b.b1.three) - ((char *)&b.b1.one), X ((char *)&b.b1.four) - ((char *)&b.b1.one)); X printf("% 4d% 4d% 4d\n", X ((char *)&b.b2.two) - ((char *)&b.b2.one), X ((char *)&b.b2.three) - ((char *)&b.b2.one), X ((char *)&b.b2.four) - ((char *)&b.b2.one)); X printf("% 4d% 4d% 4d\n", X ((char *)&b.b3.two) - ((char *)&b.b3.one), X ((char *)&b.b3.three) - ((char *)&b.b3.one), X ((char *)&b.b3.four) - ((char *)&b.b3.one)); X printf("% 4d% 4d% 4d\n\n", X ((char *)&b.b4.two) - ((char *)&b.b4.one), X ((char *)&b.b4.three) - ((char *)&b.b4.one), X ((char *)&b.b4.four) - ((char *)&b.b4.one)); X printf(" % 4d% 4d\n", sizeof b.b1, (char *)&b.b1 - (char *)&b); X printf(" % 4d% 4d\n", sizeof b.b2, (char *)&b.b2 - (char *)&b); X printf(" % 4d% 4d\n", sizeof b.b3, (char *)&b.b3 - (char *)&b); X printf(" % 4d% 4d\n", sizeof b.b4, (char *)&b.b4 - (char *)&b); X exit(0); X} END_OF_FILE if test 2439 -ne `wc -c <'packtest.c'`; then echo shar: \"'packtest.c'\" unpacked with wrong size! fi # end of 'packtest.c' fi echo shar: End of shell archive. exit 0 -- Chip Salzenberg at Teltronics/TCT <chip@tct.uucp>, <uunet!pdn!tct!chip> "I want to mention that my opinions whether real or not are MY opinions." -- the inevitable William "Billy" Steinmetz