Support MASM segments
authorRobert Pengelly <robertapengelly@hotmail.com>
Mon, 16 Sep 2024 14:35:02 +0000 (15:35 +0100)
committerRobert Pengelly <robertapengelly@hotmail.com>
Mon, 16 Sep 2024 14:35:02 +0000 (15:35 +0100)
as.h
intel.c
process.c

diff --git a/as.h b/as.h
index d33151ca0be26c51882d07226007dbc2bcccf404..2431e45fb5a1ef0a30f38ff963ca3d00da5e43d9 100644 (file)
--- a/as.h
+++ b/as.h
@@ -20,6 +20,16 @@ struct proc {
 
 };
 
+struct segment {
+
+    char *name, *old_section, *old_cpu;
+    int old_bits;
+    
+    char *filename;
+    unsigned long line_number;
+
+};
+
 #define     AS_OUTPUT_OBJ               0x00
 #define     AS_OUTPUT_BIN               0x01
 
@@ -32,6 +42,8 @@ struct as_state {
     int model, data_size;
     
     struct vector procs;
+    struct vector segs;
+    
     char *ext;
     
     struct symbol *end_symbol;
diff --git a/intel.c b/intel.c
index 31644ec507f89c12f2a0d9d14450bdb7ff626f4c..45b6a6e9a6f2ee1bbb055df179fb422cefa4dbca 100644 (file)
--- a/intel.c
+++ b/intel.c
@@ -1524,13 +1524,119 @@ void machine_dependent_handle_proc (char *start, char **pp, char *name) {
 
 }
 
-void machine_dependent_handle_endp (char *start, char **pp, char *name) {
+void machine_dependent_handle_segment (char *start, char **pp, char *name) {
+
+    struct segment *seg;
+    char *caret, *arg, saved_ch;
+    
+    seg = xmalloc (sizeof (*seg));
+    seg->name = xstrdup (name);
+    
+    seg->filename = xstrdup (get_filename ());
+    seg->line_number = get_line_number ();
+    
+    vec_push (&state->segs, (void *) seg);
+    
+    seg->old_bits = bits;
+    seg->old_section = xstrdup (section_get_name (current_section));
+    
+    if (cpu_arch_name) {
+    
+        seg->old_cpu = xmalloc (strlen (cpu_arch_name) + 1);
+        strcpy (seg->old_cpu, cpu_arch_name);
+    
+    }
+    
+    if (cpu_extensions_name && strcmp (cpu_extensions_name, "")) {
+    
+        if (cpu_arch_name) {
+        
+            seg->old_cpu = xrealloc (seg->old_cpu, strlen (cpu_arch_name) + 1 + strlen (cpu_extensions_name) + 1);
+            sprintf (seg->old_cpu, "%s+%s", cpu_arch_name, cpu_extensions_name + 1);
+        
+        } else {
+        
+            seg->old_cpu = xmalloc (strlen (cpu_extensions_name) + 1);
+            strcpy (seg->old_cpu, cpu_extensions_name + 1);
+        
+        }
+    
+    }
+    
+    caret = (*pp = skip_whitespace (*pp));
+    
+    while (!is_end_of_line[(int) *caret]) {
+    
+        if (**pp == '\'') {
+        
+            arg = ++(*pp);
+            
+            while (!is_end_of_line[(int) **pp] && **pp != '\'') {
+                (*pp)++;
+            }
+            
+            saved_ch = **pp;
+            **pp = '\0';
+        
+        } else {
+        
+            arg = symname (pp);
+            saved_ch = 0;
+        
+        }
+        
+        if (!arg) {
+            break;
+        }
+        
+        if (xstrcasecmp (arg, "use16") == 0) {
+        
+            machine_dependent_set_march ("i8086+8087");
+            bits = 16;
+        
+        } else if (xstrcasecmp (arg, "use32") == 0) {
+        
+            machine_dependent_set_march ("i386+387");
+            bits = 32;
+        
+        } else if (xstrcasecmp (arg, "code")) {
+            section_set_by_name (".text");
+        } else if (xstrcasecmp (arg, "data")) {
+            section_set_by_name (".data");
+        } else if (xstrcasecmp (arg, "bss")) {
+            section_set_by_name (".bss");
+        } else {
+        
+            **pp = saved_ch;
+            
+            report_line_at (get_filename (), get_line_number (), REPORT_ERROR, start, caret, "invalid option passed to segment");
+            ignore_rest_of_line (pp);
+            
+            return;
+        
+        }
+        
+        if (saved_ch) { **pp = saved_ch; };
+        
+        if (**pp == '\'') { (*pp)++; }
+        caret = (*pp = skip_whitespace (*pp));
+    
+    }
+    
+    if (!is_end_of_line[(int) **pp]) {
+    
+        report_at (get_filename (), get_line_number (), REPORT_ERROR, "invalid option passed to segment");
+        ignore_rest_of_line (pp);
+    
+    }
+
+}
+
+void machine_dependent_handle_endp (char *start, char *name) {
 
     struct proc *proc;
     int last;
     
-    (void) pp;
-    
     if (state->procs.length == 0) {
     
         report_at (get_filename (), get_line_number (), REPORT_ERROR, "block nesting error");
@@ -1550,8 +1656,47 @@ void machine_dependent_handle_endp (char *start, char **pp, char *name) {
     
     free (proc->name);
     free (proc->filename);
+    free (vec_pop (&state->procs));
+
+}
+
+void machine_dependent_handle_ends (char *start, char *name) {
+
+    struct segment *seg;
+    int last;
+    
+    if (state->segs.length == 0) {
+    
+        report_at (get_filename (), get_line_number (), REPORT_ERROR, "block nesting error");
+        return;
+    
+    }
+    
+    last = state->segs.length - 1;
+    seg = state->segs.data[last];
+    
+    if (strcmp (seg->name, name)) {
+    
+        report_line_at (get_filename (), get_line_number (), REPORT_ERROR, start, skip_whitespace (start), "segment name does not match");
+        return;
+    
+    }
+    
+    section_set_by_name (seg->old_section);
+    free (seg->old_section);
+    
+    bits = seg->old_bits;
+    
+    if (seg->old_cpu) {
+    
+        machine_dependent_set_march (seg->old_cpu);
+        free (seg->old_cpu);
+    
+    }
     
-    vec_pop (&state->procs);
+    free (seg->name);
+    free (seg->filename);
+    free (vec_pop (&state->segs));
 
 }
 
index 892262847f6d0993c7b7ba79ab496875f8f4b908..2e329e4c9c57f6053906cd9bef3ce1b543ac7851 100644 (file)
--- a/process.c
+++ b/process.c
@@ -1067,8 +1067,12 @@ static void handle_org (char *start, char **pp) {
 }
 
 extern void machine_dependent_assemble_line (char *start, char *line);
+
 extern void machine_dependent_handle_proc (char *start, char **pp, char *name);
-extern void machine_dependent_handle_endp (char *start, char **pp, char *name);
+extern void machine_dependent_handle_endp (char *start, char *name);
+
+extern void machine_dependent_handle_segment (char *start, char **pp, char *name);
+extern void machine_dependent_handle_ends (char *start, char *name);
 
 static char *find_end_of_line (char *line) {
 
@@ -1148,6 +1152,15 @@ static void process_line (char *line, char *line_end) {
             
             }
             
+            if (xstrcasecmp (arg, "segment") == 0 || xstrcasecmp (arg, "ends") == 0) {
+            
+                report_line_at (get_filename (), get_line_number (), REPORT_ERROR, start, caret, "segment must have a name");
+                
+                ignore_rest_of_line (&line);
+                goto check;
+            
+            }
+            
             line = skip_whitespace (line);
             
             if ((poe = find_poe (arg))) {
@@ -1247,7 +1260,25 @@ static void process_line (char *line, char *line_end) {
                     
                     if (xstrcasecmp (directive, "endp") == 0) {
                     
-                        machine_dependent_handle_endp (start, &line, arg);
+                        machine_dependent_handle_endp (start, arg);
+                        
+                        free (directive);
+                        goto check;
+                    
+                    }
+                    
+                    if (xstrcasecmp (directive, "segment") == 0) {
+                    
+                        machine_dependent_handle_segment (start, &line, arg);
+                        
+                        free (directive);
+                        goto check;
+                    
+                    }
+                    
+                    if (xstrcasecmp (directive, "ends") == 0) {
+                    
+                        machine_dependent_handle_ends (start, arg);
                         
                         free (directive);
                         goto check;
@@ -1299,7 +1330,7 @@ void process_file (const char *ifile) {
     void *load_line_internal_data = NULL;
     
     struct cond *cond;
-    int cond_idx, proc_idx;
+    int cond_idx, proc_idx, seg_idx;
     
     struct hashtab_name *key;
     struct macro *m;
@@ -1486,6 +1517,13 @@ void process_file (const char *ifile) {
             report_at (proc->filename, proc->line_number, REPORT_ERROR, "procedure %s is not closed", proc->name);
         
         }
+        
+        for (seg_idx = 0; seg_idx < state->segs.length; seg_idx++) {
+        
+            struct segment *seg = (struct segment *) state->segs.data[seg_idx];
+            report_at (seg->filename, seg->line_number, REPORT_ERROR, "segment %s is not closed", seg->name);
+        
+        }
     
     }