Allow MZ stack to be set using command line
authorRobert Pengelly <robertapengelly@hotmail.com>
Thu, 17 Apr 2025 07:09:31 +0000 (08:09 +0100)
committerRobert Pengelly <robertapengelly@hotmail.com>
Thu, 17 Apr 2025 07:09:31 +0000 (08:09 +0100)
lib.c
mz.c
mz.h

diff --git a/lib.c b/lib.c
index 7edc8bcb11aa7a03e4e6980fb4353af07ea0a164..fcb19717ddb0959c5fccf94b6d487ddd9ee8fed7 100644 (file)
--- a/lib.c
+++ b/lib.c
 
 #include    "ld.h"
 #include    "lib.h"
+#include    "mz.h"
 #include    "pe.h"
 #include    "report.h"
 
 struct options_with_use {
 
+    void (*print_help) (void);
+    
     int (*check_option) (const char *cmd_arg, int argc, char **argv, int *optind, const char **optarg);
     void (*use_option) (const char *cmd_arg, int idx, const char *optarg);
 
 };
 
-static struct options_with_use fmt_tbl[] = {
+static struct options_with_use emulation_table[] = {
 
-    {   0,                      0               },
-    {   0,                      0               },
-    {   0,                      0               },
-    {   0,                      0               },
-    {   0,                      0               },
-    {   &pe_check_option,       &pe_use_option  }
+    {   0,                      0,                      0               },
+    {   &mz_print_help,         &mz_check_option,       &mz_use_option  },
+    {   0,                      0,                      0               },
+    {   0,                      0,                      0               },
+    {   0,                      0,                      0               },
+    {   &pe_print_help,         &pe_check_option,       &pe_use_option  }
 
 };
 
@@ -77,6 +80,8 @@ static void print_usage (void) {
 
     if (program_name) {
     
+        struct options_with_use *options_with_use;
+        
         fprintf (stderr, "Usage: %s [options] file...\n\n", program_name);
         fprintf (stderr, "Options:\n\n");
         
@@ -107,8 +112,17 @@ static void print_usage (void) {
         fprintf (stderr, "    --image-base <address>            Set base address of the executable.\n");
         
         fprintf (stderr, "\n");
-        pe_print_help ();
-        fprintf (stderr, "\n");
+        
+        for (options_with_use = emulation_table; ; options_with_use++) {
+        
+            if (options_with_use->print_help) {
+            
+                options_with_use->print_help ();
+                fprintf (stderr, "\n");
+            
+            }
+        
+        }
     
     }
 
@@ -571,7 +585,7 @@ void parse_args (int argc, char **argv, int optind) {
         
         if (state->emulation != LD_EMULATION_NONE) {
         
-            options_with_use = &fmt_tbl[state->emulation - 1];
+            options_with_use = &emulation_table[state->emulation - 1];
             
             if (options_with_use->check_option && options_with_use->use_option) {
             
diff --git a/mz.c b/mz.c
index e9e43f1648030e6e9886bf42e3c3236841fc94d2..b849a69592c2c61a7dfbaca217daff55dd56582e 100644 (file)
--- a/mz.c
+++ b/mz.c
@@ -1,6 +1,8 @@
 /******************************************************************************
  * @file            mz.c
  *****************************************************************************/
+#include    <ctype.h>
+#include    <errno.h>
 #include    <stdio.h>
 #include    <stdlib.h>
 #include    <string.h>
 #include    "symbol.h"
 #include    "write7x.h"
 
+unsigned long stack_size = 0x1000;
+#define     LD_OPTION_STACK                                 1
+
+static struct ld_option opts[] = {
+
+    {   "--stack",          LD_OPTION_STACK,        LD_OPTION_HAS_ARG   },
+    {   0,                  0,                      0                   }
+
+};
+
+int mz_check_option (const char *cmd_arg, int argc, char **argv, int *optind, const char **optarg) {
+
+    struct ld_option *popt;
+    
+    for (popt = opts; ; popt++) {
+    
+        const char *p1 = popt->name;
+        const char *r1 = cmd_arg;
+        
+        if (!p1) {
+            break;    
+        }
+        
+        if (!strstart (p1, &r1)) {
+            continue;
+        }
+        
+        (*optarg) = r1;
+        
+        if (popt->flgs & LD_OPTION_HAS_ARG) {
+        
+            if (*r1 == '\0') {
+            
+                if ((*optind) >= argc) {
+                
+                    report_at (program_name, 0, REPORT_ERROR, "argument to '%s' is missing", cmd_arg);
+                    exit (EXIT_FAILURE);
+                
+                }
+                
+                (*optarg) = argv[(*optind)++];
+            
+            }
+        
+        } else if (*r1 != '\0') {
+            continue;
+        }
+        
+        return popt->idx;
+    
+    }
+    
+    return -1;
+
+}
+
+void mz_use_option (const char *cmd_arg, int idx, const char *optarg) {
+
+    switch (idx) {
+    
+        case LD_OPTION_STACK: {
+        
+            long conversion;
+            char *temp;
+            
+            errno = 0;
+            conversion = strtol (optarg, &temp, 0);
+            
+            if (!*optarg || isspace ((int) *optarg) || errno || *temp) {
+            
+                report_at (program_name, 0, REPORT_ERROR, "invalid stack number '%s'", optarg);
+                exit (EXIT_FAILURE);
+            
+            }
+            
+            stack_size = (unsigned long) conversion;
+            break;
+        
+        }
+        
+        default: {
+        
+            report_at (program_name, 0, REPORT_ERROR, "unsupported option '%s'", cmd_arg);
+            exit (EXIT_FAILURE);
+        
+        }
+    
+    }
+
+}
+
+void mz_print_help (void) {
+
+    fprintf (stderr, "ia16_mz:\n\n");
+    fprintf (stderr, "    --stack <size>                    Set size of the initial stack.\n");
+
+}
+
+
 static unsigned long section_get_num_relocs (struct section *section) {
 
     unsigned long num_relocs = 0, i;
@@ -78,8 +179,7 @@ void mz_write (const char *filename) {
     unsigned long header_size;
     
     unsigned long reloc_size = 0, reloc_count = 0;
-    unsigned long ibss_addr = 0, ibss_size = 0;
-    unsigned long stack_addr = 0, stack_size = 0;
+    unsigned long stack_addr = 0, ibss_addr = 0, ibss_size = 0;
     
     struct mz_exec exec;
     memset (&exec, 0, sizeof (exec));
@@ -132,7 +232,6 @@ void mz_write (const char *filename) {
     }
     
     stack_addr = ALIGN (ibss_addr + ibss_size, 16);
-    stack_size = 0x2000;        /* Maybe get this from command line in the future. */
     
     
     exec.e_magic[0] = 'M';
diff --git a/mz.h b/mz.h
index 309a10b0a6bf14a17e6e3f56570fc290b4dcef8e..dbf2fa5cf36d5d814986f474619334b03fc6bbe3 100644 (file)
--- a/mz.h
+++ b/mz.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * @file            pe.h
+ * @file            mz.h
  *****************************************************************************/
 #ifndef     _MZ_H
 #define     _MZ_H
@@ -26,6 +26,11 @@ struct mz_exec {
 
 };
 
+int mz_check_option (const char *cmd_arg, int argc, char **argv, int *optind, const char **optarg);
+
+void mz_print_help (void);
+void mz_use_option (const char *cmd_arg, int idx, const char *optarg);
+
 void mz_write (const char *filename);
 
 #endif      /* _MZ_H */