- /* if noun different then src overrides */
- if ( SPEC_NOUN(dest) != SPEC_NOUN(src) && !SPEC_NOUN(dest))
- SPEC_NOUN(dest) = SPEC_NOUN(src) ;
-
- if (! SPEC_SCLS(dest)) /* if destination has no storage class */
- SPEC_SCLS(dest) = SPEC_SCLS(src) ;
-
- /* copy all the specifications */
- SPEC_LONG(dest) |= SPEC_LONG(src);
- SPEC_SHORT(dest) |= SPEC_SHORT(src);
- SPEC_USIGN(dest) |= SPEC_USIGN(src);
- SPEC_STAT(dest) |= SPEC_STAT(src);
- SPEC_EXTR(dest) |= SPEC_EXTR(src);
- SPEC_ABSA(dest) |= SPEC_ABSA(src);
- SPEC_RENT(dest) |= SPEC_RENT(src);
- SPEC_INTN(dest) |= SPEC_INTN(src);
- SPEC_BANK(dest) |= SPEC_BANK(src);
- SPEC_VOLATILE(dest) |= SPEC_VOLATILE(src);
- SPEC_CRTCL(dest) |= SPEC_CRTCL(src);
- SPEC_ADDR(dest) |= SPEC_ADDR(src);
- SPEC_OCLS(dest) = SPEC_OCLS(src);
- SPEC_BLEN(dest) |= SPEC_BLEN(src);
- SPEC_BSTR(dest) |= SPEC_BSTR(src);
- SPEC_TYPEDEF(dest) |= SPEC_TYPEDEF(src);
-
- if ( IS_STRUCT(dest) && SPEC_STRUCT(dest) == NULL )
- SPEC_STRUCT(dest) = SPEC_STRUCT(src);
-
- return dest ;
+
+ sym_link *symlink=dest;
+
+#if 0
+ if (!IS_SPEC(dest)) {
+ // This can happen for pointers, find the end type
+ while (dest && !IS_SPEC(dest))
+ dest=dest->next;
+ }
+ if (!IS_SPEC(src)) {
+ // here we have a declarator as source, reverse them
+ symlink=src;
+ src=dest;
+ dest=symlink;
+ while (dest && !IS_SPEC(dest)) {
+ // and find the specifier
+ dest=dest->next;
+ }
+ } else {
+ symlink=dest;
+ }
+#endif
+
+ if (!IS_SPEC(dest) || !IS_SPEC(src)) {
+ werror (E_INTERNAL_ERROR, __FILE__, __LINE__, "cannot merge declarator");
+ exit (1);
+ }
+
+ if (getenv("DEBUG_mergeSpec")) {
+ fprintf (stderr, "mergeSpec: \"%s\"\n", name);
+ }
+
+ if (SPEC_NOUN(src)) {
+ if (!SPEC_NOUN(dest)) {
+ SPEC_NOUN(dest)=SPEC_NOUN(src);
+ } else {
+ /* we shouldn't redeclare the type */
+ if (getenv("DEBUG_SANITY")) {
+ fprintf (stderr, "mergeSpec: ");
+ }
+ werror(E_TWO_OR_MORE_DATA_TYPES, name);
+ }
+ }
+
+ if (SPEC_SCLS(src)) {
+ /* if destination has no storage class */
+ if (!SPEC_SCLS (dest) || SPEC_SCLS(dest)==S_REGISTER) {
+ SPEC_SCLS (dest) = SPEC_SCLS (src);
+ } else {
+ if (getenv("DEBUG_SANITY")) {
+ fprintf (stderr, "mergeSpec: ");
+ }
+ werror(E_TWO_OR_MORE_STORAGE_CLASSES, name);
+ }
+ }
+
+ /* copy all the specifications */
+
+ // we really should do:
+#if 0
+ if (SPEC_what(src)) {
+ if (SPEC_what(dest)) {
+ werror(W_DUPLICATE_SPEC, "what");
+ }
+ SPEC_what(dst)|=SPEC_what(src);
+ }
+#endif
+ // but there are more important thing right now
+
+ SPEC_LONG (dest) |= SPEC_LONG (src);
+ dest->select.s._short|=src->select.s._short;
+ SPEC_USIGN (dest) |= SPEC_USIGN (src);
+ dest->select.s._signed|=src->select.s._signed;
+ SPEC_STAT (dest) |= SPEC_STAT (src);
+ SPEC_EXTR (dest) |= SPEC_EXTR (src);
+ SPEC_ABSA (dest) |= SPEC_ABSA (src);
+ SPEC_RENT (dest) |= SPEC_RENT (src);
+ SPEC_INTN (dest) |= SPEC_INTN (src);
+ SPEC_BANK (dest) |= SPEC_BANK (src);
+ SPEC_VOLATILE (dest) |= SPEC_VOLATILE (src);
+ SPEC_CRTCL (dest) |= SPEC_CRTCL (src);
+ SPEC_ADDR (dest) |= SPEC_ADDR (src);
+ SPEC_OCLS (dest) = SPEC_OCLS (src);
+ SPEC_BLEN (dest) |= SPEC_BLEN (src);
+ SPEC_BSTR (dest) |= SPEC_BSTR (src);
+ SPEC_TYPEDEF (dest) |= SPEC_TYPEDEF (src);
+ SPEC_NONBANKED (dest) |= SPEC_NONBANKED (src);
+ SPEC_NAKED (dest) |= SPEC_NAKED (src);
+
+ if (IS_STRUCT (dest) && SPEC_STRUCT (dest) == NULL)
+ SPEC_STRUCT (dest) = SPEC_STRUCT (src);
+
+ return symlink;