Advertisement
doragasu

getopt_long usage

Nov 2nd, 2015
121
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.23 KB | None | 0 0
  1. // TODO: Allow direct reads/writes to GEC
  2. // TODO: Allow to specify serial port and speed to use
  3. // TODO: Support other mappers
  4. // TODO: Allow using multiple in length arguments (such as 1024KiB, 2MiB...)
  5. //       Also print lengths using these multiples
  6.  
  7. #include <unistd.h>
  8. #include <stdlib.h>
  9. #include <stdint.h>
  10. #include <stdio.h>
  11. #include <getopt.h>
  12. #include "fsm.h"
  13.  
  14. #define MAX_FILELEN     255
  15. #define VERSION_MAJOR   0x00
  16. #define VERSION_MINOR   0x01
  17.  
  18. #ifndef TRUE
  19. #define TRUE 1
  20. #endif
  21. #ifndef FALSE
  22. #define FALSE 0
  23. #endif
  24. #ifndef NULL
  25. #define NULL ((void*)0)
  26. #endif
  27.  
  28. /// Structure containing a memory image (file, address and length)
  29. typedef struct {
  30.     char *file;
  31.     uint32_t addr;
  32.     uint32_t len;
  33. } MemImage;
  34.  
  35. /// printf-like macro that writes on stderr instead of stdout
  36. #define PrintErr(...)   do{fprintf(stderr, __VA_ARGS__);}while(0)
  37.  
  38. const struct option opt[] = {
  39.     {"flash",      required_argument, NULL,     'f'},
  40.     {"read",       required_argument, NULL,     'r'},
  41.     {"erase",      no_argument,       NULL,     'e'},
  42.     {"verify",     no_argument,       NULL,     'V'},
  43.     {"write-save", required_argument, NULL,     'w'},
  44.     {"back-save",  required_argument, NULL,     'b'},
  45.     {"cart-info",  no_argument,       NULL,     'c'},
  46.     {"flash-id",   no_argument,       NULL,     'i'},
  47.     {"version",    no_argument,       NULL,     'R'},
  48.     {"verbose",    no_argument,       NULL,     'v'},
  49.     {"help",       no_argument,       NULL,     'h'},
  50.     {NULL,         0,                 NULL,      0 }
  51. };
  52.  
  53. const char *description[] = {
  54.     "Flash rom file",
  55.     "Read ROM/Flash to file",
  56.     "Erase Flash",
  57.     "Verify flash after writing file",
  58.     "Write file to SRAM",
  59.     "Backup SRAM to file",
  60.     "Show cartridge information",
  61.     "Show flash chip identification",
  62.     "Print version and exit",
  63.     "Show more information during execution",
  64.     "Print help screen and exit"
  65. };
  66.  
  67. void PrintVersion(char *prgName) {
  68.     printf("%s version %d.%d, doragasu 2015.\n", prgName,
  69.             VERSION_MAJOR, VERSION_MINOR);
  70. }
  71.  
  72. void PrintHelp(char *prgName) {
  73.     int i;
  74.  
  75.     PrintVersion(prgName);
  76.     printf("Usage: %s [OPTIONS [OPTION_ARG]]\nSupported options:\n\n", prgName);
  77.     for (i = 0; opt[i].name; i++) {
  78.         printf(" -%c, --%s%s: %s.\n", opt[i].val, opt[i].name,
  79.                 opt[i].has_arg == required_argument?" <arg>":"",
  80.                 description[i]);
  81.     }
  82.     // Print additional info
  83.     printf("For file arguments, it is possible to specify start address and "
  84.            "file length to read/write in bytes, with the following format:\n"
  85.            "    file_name:memory_address:file_length\n\n"
  86.            "Examples:\n"
  87.            " - Erase Flash and write entire ROM to cartridge: %s -ef rom_file\n"
  88.            " - Flash and verify 32 KiB to 0x700000: "
  89.            "%s -Vf rom_file:0x700000:32768\n"
  90.            " - Dump 1 MiB of the cartridge: %s -r rom_file::1048576\n"
  91.            " - Backup cartridge SRAM: %s --back-save saver_file\n\n"
  92.            "SRAM reads/writes must fall within the hex range 0~7FFF\n"
  93.            "ROM/Flash reads/writes must fall within the hex range 0~7FFFFF\n",
  94.            prgName, prgName, prgName, prgName);
  95.            
  96. }
  97.  
  98. /// Receives a MemImage pointer with full info in file name (e.g.
  99. /// m->file = "rom.bin:6000:1"). Removes from m->file information other
  100. /// than the file name, and fills the remaining structure fields if info
  101. /// is provided (e.g. info in previous example would cause m = {"rom.bin",
  102. /// 0x6000, 1}).
  103. int ParseMemArgument(MemImage *m) {
  104.     int i;
  105.     char *addr = NULL;
  106.     char *len  = NULL;
  107.     char *endPtr;
  108.  
  109.     // Set address and length to default values
  110.     m->len = m->addr = 0;
  111.  
  112.     // First argument is name. Find where it ends
  113.     for (i = 0; i < (MAX_FILELEN + 1) && m->file[i] != '\0' &&
  114.             m->file[i] != ':'; i++);
  115.     // Check if end reached without finding end of string
  116.     if (i == MAX_FILELEN + 1) return 1;
  117.     if (m->file[i] == '\0') return 0;
  118.    
  119.     // End of token marker, search address
  120.     m->file[i++] = '\0';
  121.     addr = m->file + i;
  122.     for (; i < (MAX_FILELEN + 1) && m->file[i] != '\0' && m->file[i] != ':';
  123.             i++);
  124.     // Check if end reached without finding end of string
  125.     if (i == MAX_FILELEN + 1) return 1;
  126.     // If end of token marker, search length
  127.     if (m->file[i] == ':') {
  128.         m->file[i++] = '\0';
  129.         len = m->file + i;
  130.         // Verify there's an end of string
  131.         for (; i < (MAX_FILELEN + 1) && m->file[i] != '\0'; i++);
  132.         if (m->file[i] != '\0') return 1;
  133.     }
  134.     // Convert strings to numbers and return
  135.     if (addr && *addr) m->addr = strtol(addr, &endPtr, 0);
  136.     if (m->addr == 0 && addr == endPtr) return 2;
  137.     if (len  && *len)  m->len  = strtol(len, &endPtr, 0);
  138.     if (m->len  == 0 && len  == endPtr) return 3;
  139.  
  140.     return 0;
  141. }
  142.  
  143. void PrintMemImage(MemImage *m) {
  144.     printf("%s", m->file);
  145.     if (m->addr) printf(" at address 0x%06X", m->addr);
  146.     if (m->len ) printf(" (%d bytes)", m->len);
  147. }
  148.  
  149. void PrintMemError(int code) {
  150.     switch (code) {
  151.         case 0: printf("Memory range OK.\n"); break;
  152.         case 1: PrintErr("Invalid memory range string.\n"); break;
  153.         case 2: PrintErr("Invalid memory address.\n"); break;
  154.         case 3: PrintErr("Invalid memory length.\n"); break;
  155.         default: PrintErr("Unknown memory specification error.\n");
  156.     }
  157. }
  158.  
  159. int main(int argc, char **argv) {
  160.     /// Option index, for command line options parsing
  161.     int opIdx = 0;
  162.     /// Character returned by getopt_long()
  163.     int c;
  164.     /// Erase flash if TRUE
  165.     int erase = FALSE;
  166.     /// Verify flash write if TRUE
  167.     int verify = FALSE;
  168.     /// Print extra information on screen
  169.     int verbose = FALSE;
  170.     /// Show cartridge information
  171.     int cartInfo = FALSE;
  172.     /// Show flash chip id
  173.     int flashId = FALSE;
  174.     /// Rom file to write to flash
  175.     MemImage fWr = {NULL, 0, 0};
  176.     /// Rom file to read from flash (default read length: 1 MiB)
  177.     MemImage fRd = {NULL, 0, 1024*1024};
  178.     /// Ram file to write
  179.     MemImage rWr = {NULL, 0, 0};
  180.     /// Ram file to read (default read length: 32 KiB)
  181.     MemImage rRd = {NULL, 0, 32*1024};
  182.     /// Error code for function calls
  183.     int errCode;
  184.  
  185.  
  186.     /// Parse command line switches
  187.     if (1 == argc) {
  188.         printf("Nothing to do!\n");
  189.         PrintHelp(argv[0]);
  190.         return 0;
  191.     }
  192.     while ((c = getopt_long(argc, argv, "f:r:eVw:b:ciRvh", opt,
  193.                     &opIdx)) != -1) {
  194.         // Parse command-line options
  195.         switch (c) {
  196.             case 'f':   // Write flash
  197.                 fWr.file = optarg;
  198.                 if ((errCode = ParseMemArgument(&fWr))) {
  199.                     PrintErr("Error: On Flash file argument: ");
  200.                     PrintMemError(errCode);
  201.                     return 1;
  202.                 }
  203.                 break;
  204.  
  205.             case 'r':   // Read flash
  206.                 fRd.file = optarg;
  207.                 if ((errCode = ParseMemArgument(&fRd))) {
  208.                     PrintErr("Error: On ROM/Flash read argument: ");
  209.                     PrintMemError(errCode);
  210.                     return 1;
  211.                 }
  212.                 break;
  213.  
  214.             case 'e':   // Erase flash
  215.                 erase = TRUE;
  216.                 break;
  217.  
  218.             case 'V':   // Verify flash write
  219.                 verify = TRUE;
  220.                 break;
  221.  
  222.             case 'w':   // Write RAM
  223.                 rWr.file = optarg;
  224.                 if ((errCode = ParseMemArgument(&rWr))) {
  225.                     PrintErr("Error: On RAM write argument: ");
  226.                     PrintMemError(errCode);
  227.                     return 1;
  228.                 }
  229.                 break;
  230.  
  231.             case 'b':   // Read RAM
  232.                 rRd.file = optarg;
  233.                 if ((errCode = ParseMemArgument(&rRd))) {
  234.                     PrintErr("Error: On RAM read argument: ");
  235.                     PrintMemError(errCode);
  236.                     return 1;
  237.                 }
  238.                 break;
  239.  
  240.             case 'c':   // Cart info
  241.                 cartInfo = TRUE;
  242.                 break;
  243.  
  244.             case 'i':   // Flash chip id
  245.                 flashId = TRUE;
  246.                 break;
  247.  
  248.             case 'R':   // Print program version
  249.                 PrintVersion(argv[0]);
  250.                 return 0;
  251.  
  252.             case 'v':   // Verbose
  253.                 verbose = TRUE;
  254.                 break;
  255.  
  256.             case 'h':   // Print help
  257.                 PrintHelp(argv[0]);
  258.                 return 0;
  259.  
  260.             case '?':   // Unknown switch
  261.                 PrintHelp(argv[0]);
  262.                 return 1;
  263.         }
  264.     }
  265.  
  266.     // If verbose, print config
  267.     if (verbose) {
  268.         printf("The following actions will be performed (in order):\n");
  269.         printf("==================================================\n\n");
  270.         if (cartInfo) printf(" - Show cartridge header information.\n");
  271.         if (flashId) printf(" - Show Flash chip identification.\n");
  272.         if (erase) printf(" - Erase Flash.\n");
  273.         if (fWr.file) {
  274.            printf(" - Flash %s", verify?"and verify ":"");
  275.            PrintMemImage(&fWr); putchar('\n');
  276.         }
  277.         if (fRd.file) {
  278.             printf(" - Read ROM/Flash to ");
  279.             PrintMemImage(&fRd); putchar('\n');
  280.         }
  281.         if (rWr.file) {
  282.             printf(" - Write to SRAM ");
  283.             PrintMemImage(&rWr); putchar('\n');
  284.         }
  285.         if (rRd.file) {
  286.             printf(" - Read SRAM to ");
  287.             PrintMemImage(&rRd); putchar('\n');
  288.         }
  289.         printf("\n");
  290.     }
  291.     return 0;
  292. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement