Fixed local initialization
authorRobert Pengelly <robertapengelly@hotmail.com>
Thu, 16 Jul 2026 08:03:38 +0000 (09:03 +0100)
committerRobert Pengelly <robertapengelly@hotmail.com>
Thu, 16 Jul 2026 08:03:38 +0000 (09:03 +0100)
amd64.c
i386.c

diff --git a/amd64.c b/amd64.c
index ca75b133c453fcf6f4f91863e0c0b8cb262e4814..14633812b2973ed2d759539af135b287fe1d65b7 100644 (file)
--- a/amd64.c
+++ b/amd64.c
@@ -8313,12 +8313,28 @@ static void parse_local_string_field_initializer (struct local_init *inits, int
 
 }
 
-static void parse_local_aggregate_initializer_values (struct local_init *inits, int *init_count, int max_inits, long base_offset, const int *fields, int field_count) {
+static void append_local_zero_initializer (struct local_init *inits, int *init_count, int max_inits, long offset, int size) {
 
-    int field_index = 0;
-    int braced = 0;
+    if (*init_count >= max_inits) {
+        return;
+    }
     
-    long field_offset = 0;
+    inits[*init_count].offset = offset;
+    inits[*init_count].size = size;
+    inits[*init_count].kind = LOCAL_INIT_CONST;
+    inits[*init_count].symbol = 0;
+    inits[*init_count].value.low = 0;
+    inits[*init_count].value.high = 0;
+    inits[*init_count].source_offset = 0;
+    inits[*init_count].source_size = 0;
+    
+    (*init_count)++;
+
+}
+
+static void parse_local_aggregate_initializer_group (struct local_init *inits, int *init_count, int max_inits, long base_offset, const int *fields, int field_count, int *field_index, long *field_offset) {
+
+    int braced = 0;
     
     if (tok.kind == TOK_LBRACE) {
     
@@ -8327,115 +8343,87 @@ static void parse_local_aggregate_initializer_values (struct local_init *inits,
     
     }
     
-    while (field_index < field_count) {
+    while (*field_index < field_count) {
     
-        int field_size = fields[field_index];
+        int field_size;
         
-        if (field_size < 0) {
+        while (*field_index < field_count && fields[*field_index] < 0) {
         
-            field_offset += -field_size;
-            
-            field_index++;
-            continue;
+            *field_offset += -fields[*field_index];
+            (*field_index)++;
         
         }
         
+        if (*field_index >= field_count) {
+            break;
+        }
+        
         if (braced && tok.kind == TOK_RBRACE) {
         
+            get_token ();
+            return;
+        
+        }
+        
+        field_size = fields[*field_index];
+        
+        if (tok.kind == TOK_LBRACE) {
+            parse_local_aggregate_initializer_group (inits, init_count, max_inits, base_offset, fields, field_count, field_index, field_offset);
+        } else {
+        
             if (*init_count < max_inits) {
             
-                inits[*init_count].offset = base_offset + field_offset;
-                inits[*init_count].size = field_size;
-                inits[*init_count].kind = LOCAL_INIT_CONST;
-                inits[*init_count].symbol = 0;
-                inits[*init_count].value.low = 0;
-                inits[*init_count].value.high = 0;
-                inits[*init_count].source_offset = 0;
-                inits[*init_count].source_size = 0;
+                if (is_string_token ()) {
+                    parse_local_string_field_initializer (inits, init_count, max_inits, base_offset + *field_offset, field_size);
+                } else {
                 
-                (*init_count)++;
+                    inits[*init_count].offset = base_offset + *field_offset;
+                    inits[*init_count].size = field_size;
+                    
+                    parse_local_initializer_value (&inits[*init_count], 0, 0);
+                    (*init_count)++;
+                
+                }
             
+            } else {
+                skip_initializer ();
             }
             
-            field_offset += field_size;
-            field_index++;
-            
-            continue;
+            *field_offset += field_size;
+            (*field_index)++;
         
         }
         
-        if (*init_count < max_inits) {
+        if (!braced) {
+            return;
+        }
         
-            if (is_string_token ()) {
-                parse_local_string_field_initializer (inits, init_count, max_inits, base_offset + field_offset, field_size);
-            } else {
+        if (_accept (TOK_COMMA)) {
+        
+            if (tok.kind == TOK_RBRACE) {
             
-                inits[*init_count].offset = base_offset + field_offset;
-                inits[*init_count].size = field_size;
-                
-                parse_local_initializer_value (&inits[*init_count], 0, 0);
-                (*init_count)++;
+                get_token ();
+                return;
             
             }
+            
+            continue;
         
-        } else {
-            skip_initializer ();
         }
         
-        field_offset += field_size;
-        field_index++;
-        
-        if (braced) {
+        if (tok.kind == TOK_RBRACE) {
         
-            if (!_accept (TOK_COMMA)) {
-                break;
-            }
-            
-            if (tok.kind == TOK_RBRACE) {
-                break;
-            }
+            get_token ();
+            return;
         
-        } else {
-            break;
         }
+        
+        break;
     
     }
     
     if (braced) {
     
-        while (field_index < field_count) {
-        
-            int field_size = fields[field_index];
-            
-            if (field_size < 0) {
-            
-                field_offset += -field_size;
-                
-                field_index++;
-                continue;
-            
-            }
-            
-            if (*init_count < max_inits) {
-            
-                inits[*init_count].offset = base_offset + field_offset;
-                inits[*init_count].size = field_size;
-                inits[*init_count].kind = LOCAL_INIT_CONST;
-                inits[*init_count].symbol = 0;
-                inits[*init_count].value.low = 0;
-                inits[*init_count].value.high = 0;
-                inits[*init_count].source_offset = 0;
-                inits[*init_count].source_size = 0;
-                
-                (*init_count)++;
-            
-            }
-            
-            field_offset += field_size;
-            field_index++;
-        
-        }
-        
         while (tok.kind != TOK_EOF && tok.kind != TOK_RBRACE) {
         
             skip_initializer ();
@@ -8443,6 +8431,7 @@ static void parse_local_aggregate_initializer_values (struct local_init *inits,
             if (!_accept (TOK_COMMA)) {
                 break;
             }
+        
         }
         
         expect (TOK_RBRACE, "}");
@@ -8451,6 +8440,32 @@ static void parse_local_aggregate_initializer_values (struct local_init *inits,
 
 }
 
+static void parse_local_aggregate_initializer_values (struct local_init *inits, int *init_count, int max_inits, long base_offset, const int *fields, int field_count) {
+
+    int field_index = 0;
+    long field_offset = 0;
+    
+    parse_local_aggregate_initializer_group (inits, init_count, max_inits, base_offset, fields, field_count, &field_index, &field_offset);
+    
+    while (field_index < field_count) {
+    
+        int field_size = fields[field_index];
+        
+        if (field_size < 0) {
+            field_offset += -field_size;
+        } else {
+        
+            append_local_zero_initializer (inits, init_count, max_inits, base_offset + field_offset, field_size);
+            field_offset += field_size;
+        
+        }
+        
+        field_index++;
+    
+    }
+
+}
+
 static void make_local_static_label (char *buf, size_t bufsz, const char *name) {
 
     if (!buf || bufsz == 0) {
diff --git a/i386.c b/i386.c
index 67e82f937b6ac5ba0b38e3d160d8b73ab44d27c6..723d02b95d402c2dd9238fd3abb1b1ed15e4ba6a 100644 (file)
--- a/i386.c
+++ b/i386.c
@@ -7529,12 +7529,28 @@ static void parse_local_string_field_initializer (struct local_init *inits, int
 
 }
 
-static void parse_local_aggregate_initializer_values (struct local_init *inits, int *init_count, int max_inits, long base_offset, const int *fields, int field_count) {
+static void append_local_zero_initializer (struct local_init *inits, int *init_count, int max_inits, long offset, int size) {
 
-    int field_index = 0;
-    int braced = 0;
+    if (*init_count >= max_inits) {
+        return;
+    }
     
-    long field_offset = 0;
+    inits[*init_count].offset = offset;
+    inits[*init_count].size = size;
+    inits[*init_count].kind = LOCAL_INIT_CONST;
+    inits[*init_count].symbol = 0;
+    inits[*init_count].value.low = 0;
+    inits[*init_count].value.high = 0;
+    inits[*init_count].source_offset = 0;
+    inits[*init_count].source_size = 0;
+    
+    (*init_count)++;
+
+}
+
+static void parse_local_aggregate_initializer_group (struct local_init *inits, int *init_count, int max_inits, long base_offset, const int *fields, int field_count, int *field_index, long *field_offset) {
+
+    int braced = 0;
     
     if (tok.kind == TOK_LBRACE) {
     
@@ -7543,115 +7559,87 @@ static void parse_local_aggregate_initializer_values (struct local_init *inits,
     
     }
     
-    while (field_index < field_count) {
+    while (*field_index < field_count) {
     
-        int field_size = fields[field_index];
+        int field_size;
         
-        if (field_size < 0) {
+        while (*field_index < field_count && fields[*field_index] < 0) {
         
-            field_offset += -field_size;
-            
-            field_index++;
-            continue;
+            *field_offset += -fields[*field_index];
+            (*field_index)++;
         
         }
         
+        if (*field_index >= field_count) {
+            break;
+        }
+        
         if (braced && tok.kind == TOK_RBRACE) {
         
+            get_token ();
+            return;
+        
+        }
+        
+        field_size = fields[*field_index];
+        
+        if (tok.kind == TOK_LBRACE) {
+            parse_local_aggregate_initializer_group (inits, init_count, max_inits, base_offset, fields, field_count, field_index, field_offset);
+        } else {
+        
             if (*init_count < max_inits) {
             
-                inits[*init_count].offset = base_offset + field_offset;
-                inits[*init_count].size = field_size;
-                inits[*init_count].kind = LOCAL_INIT_CONST;
-                inits[*init_count].symbol = 0;
-                inits[*init_count].value.low = 0;
-                inits[*init_count].value.high = 0;
-                inits[*init_count].source_offset = 0;
-                inits[*init_count].source_size = 0;
+                if (is_string_token ()) {
+                    parse_local_string_field_initializer (inits, init_count, max_inits, base_offset + *field_offset, field_size);
+                } else {
                 
-                (*init_count)++;
+                    inits[*init_count].offset = base_offset + *field_offset;
+                    inits[*init_count].size = field_size;
+                    
+                    parse_local_initializer_value (&inits[*init_count], 0, 0);
+                    (*init_count)++;
+                
+                }
             
+            } else {
+                skip_initializer ();
             }
             
-            field_offset += field_size;
-            field_index++;
-            
-            continue;
+            *field_offset += field_size;
+            (*field_index)++;
         
         }
         
-        if (*init_count < max_inits) {
+        if (!braced) {
+            return;
+        }
         
-            if (is_string_token ()) {
-                parse_local_string_field_initializer (inits, init_count, max_inits, base_offset + field_offset, field_size);
-            } else {
+        if (_accept (TOK_COMMA)) {
+        
+            if (tok.kind == TOK_RBRACE) {
             
-                inits[*init_count].offset = base_offset + field_offset;
-                inits[*init_count].size = field_size;
-                
-                parse_local_initializer_value (&inits[*init_count], 0, 0);
-                (*init_count)++;
+                get_token ();
+                return;
             
             }
+            
+            continue;
         
-        } else {
-            skip_initializer ();
         }
         
-        field_offset += field_size;
-        field_index++;
-        
-        if (braced) {
+        if (tok.kind == TOK_RBRACE) {
         
-            if (!_accept (TOK_COMMA)) {
-                break;
-            }
-            
-            if (tok.kind == TOK_RBRACE) {
-                break;
-            }
+            get_token ();
+            return;
         
-        } else {
-            break;
         }
+        
+        break;
     
     }
     
     if (braced) {
     
-        while (field_index < field_count) {
-        
-            int field_size = fields[field_index];
-            
-            if (field_size < 0) {
-            
-                field_offset += -field_size;
-                
-                field_index++;
-                continue;
-            
-            }
-            
-            if (*init_count < max_inits) {
-            
-                inits[*init_count].offset = base_offset + field_offset;
-                inits[*init_count].size = field_size;
-                inits[*init_count].kind = LOCAL_INIT_CONST;
-                inits[*init_count].symbol = 0;
-                inits[*init_count].value.low = 0;
-                inits[*init_count].value.high = 0;
-                inits[*init_count].source_offset = 0;
-                inits[*init_count].source_size = 0;
-                
-                (*init_count)++;
-            
-            }
-            
-            field_offset += field_size;
-            field_index++;
-        
-        }
-        
         while (tok.kind != TOK_EOF && tok.kind != TOK_RBRACE) {
         
             skip_initializer ();
@@ -7659,6 +7647,7 @@ static void parse_local_aggregate_initializer_values (struct local_init *inits,
             if (!_accept (TOK_COMMA)) {
                 break;
             }
+        
         }
         
         expect (TOK_RBRACE, "}");
@@ -7667,6 +7656,32 @@ static void parse_local_aggregate_initializer_values (struct local_init *inits,
 
 }
 
+static void parse_local_aggregate_initializer_values (struct local_init *inits, int *init_count, int max_inits, long base_offset, const int *fields, int field_count) {
+
+    int field_index = 0;
+    long field_offset = 0;
+    
+    parse_local_aggregate_initializer_group (inits, init_count, max_inits, base_offset, fields, field_count, &field_index, &field_offset);
+    
+    while (field_index < field_count) {
+    
+        int field_size = fields[field_index];
+        
+        if (field_size < 0) {
+            field_offset += -field_size;
+        } else {
+        
+            append_local_zero_initializer (inits, init_count, max_inits, base_offset + field_offset, field_size);
+            field_offset += field_size;
+        
+        }
+        
+        field_index++;
+    
+    }
+
+}
+
 static void make_local_static_label (char *buf, size_t bufsz, const char *name) {
 
     if (!buf || bufsz == 0) {