?login_element?

Subversion Repositories NedoOS

Rev

Blame | Last modification | View Log | Download

  1. /* parser.c - source file parser library.
  2.  
  3.    This is free and unencumbered software released into the public domain.
  4.    For more information, please refer to <http://unlicense.org>. */
  5.  
  6. #include "defs.h"
  7.  
  8. #include <stdbool.h>
  9. #include <string.h>
  10. #include <stdlib.h>
  11. #include <ctype.h>
  12. #include "debug.h"
  13. #include "l_ifile.h"
  14. #include "parser.h"
  15.  
  16. const struct
  17. {
  18.     char *name;
  19.     unsigned syntax;
  20. }
  21. syntaxes[] =
  22. {
  23.     { "tasm", SYNTAX_TASM },
  24.     { "sjasm", SYNTAX_SJASM },
  25.     { NULL, 0 }
  26. };
  27.  
  28. bool _str_to_syntax (const char *name, unsigned *syntax)
  29. {
  30.     unsigned i;
  31.     for (i = 0; syntaxes[i].name; i++)
  32.     {
  33.         if (!strcmp (syntaxes[i].name, name))
  34.         {
  35.             *syntax = syntaxes[i].syntax;
  36.             return true;
  37.         }
  38.     }
  39.     return false;
  40. }
  41.  
  42. bool _syntax_to_str (unsigned syntax, const char **name)
  43. {
  44.     unsigned i;
  45.     for (i = 0; syntaxes[i].name; i++)
  46.     {
  47.         if (syntaxes[i].syntax == syntax)
  48.         {
  49.             *name = syntaxes[i].name;
  50.             return true;
  51.         }
  52.     }
  53.     return false;
  54. }
  55.  
  56. const char *_skip_blanks (const char *s)
  57. {
  58.     if (s) while (*s != '\0' && isblank(*s)) s++;
  59.     return s;
  60. }
  61.  
  62. const char *_skip_word (const char *s)
  63. {
  64.     if (s)
  65.     {
  66.         if (*s == '_' || isalpha(*s))
  67.         {
  68.             s++;
  69.             while (*s != '\0' && isalnum(*s)) s++;
  70.         }
  71.     }
  72.     return s;
  73. }
  74.  
  75. const char *_skip_string (const char *s)
  76. {
  77.     const char *p;
  78.     p = s;
  79.     if (p)
  80.     {
  81.         if (*p == '"')
  82.         {
  83.             p++;        // Skip opening double quote character
  84.             while (*p != '\0' && *p != '"') p++;
  85.             if (*p == '"')
  86.                 p++;    // Skip closing double quote character
  87.             else
  88.                 p = s;  // Fail
  89.         }
  90.     }
  91.     return p;
  92. }
  93.  
  94. #define TEXT_BUF_SIZE 15
  95. char get_include_tasm (const char *s, unsigned *flags, char **name)
  96. {
  97.     char st;
  98.     char buf[TEXT_BUF_SIZE+1];
  99.     const char *endp, *np;
  100.     unsigned sl, nl;
  101.     unsigned inc_flags;
  102.     char *inc_name;
  103.  
  104.     st = PARST_SKIP;
  105.     inc_name = (char *) NULL;
  106.  
  107.     if (!flags || !name)
  108.         goto _error_exit;
  109.  
  110.     // RegEx pattern: [[:space:]]*include[[:space:]]+"[^[:space:]]+"
  111.     // The rest of a line is not analized.
  112.  
  113.     // blanks
  114.     endp = _skip_blanks (s);
  115.     if (*endp == '\0')
  116.         goto _skip_line;
  117.     // assembler directive
  118.     s = endp;
  119.     endp = _skip_word (s);
  120.     if (s == endp || *endp == '\0')
  121.         goto _skip_line;
  122.     // (save it)
  123.     sl = endp - s;
  124.     if (sl > TEXT_BUF_SIZE)
  125.         sl = TEXT_BUF_SIZE;
  126.     memcpy (buf, s, sl);
  127.     buf[sl] = '\0';
  128.     // (check it)
  129.     if (!strcasecmp (buf, "include"))
  130.         inc_flags = SRCFL_PARSE;
  131.     else
  132.         goto _skip_line;
  133.     // blanks
  134.     s = endp;
  135.     endp = _skip_blanks (s);
  136.     if (s == endp || *endp == '\0')
  137.         goto _skip_line;
  138.     // string
  139.     s = endp;
  140.     endp = _skip_string (s);
  141.     if (s == endp)
  142.         goto _skip_line;
  143.     // (save it)
  144.     np = s + 1;         // skip opening double quotes character
  145.     nl = endp - s - 2;  // excluding double quotes characters
  146.     inc_name = malloc (nl + 1); // including terminating zero
  147.     if (!inc_name)
  148.     {
  149.         // Fail
  150.         _perror ("malloc");
  151.         goto _error_exit;
  152.     }
  153.     memcpy (inc_name, np, nl);
  154.     inc_name[nl] = '\0';
  155.     // (done)
  156.     st = PARST_OK;
  157.     *flags = inc_flags;
  158.     *name = inc_name;
  159.     goto _local_exit;
  160.  
  161. _skip_line:
  162.     st = PARST_SKIP;
  163.     goto _local_exit;
  164.  
  165. _error_exit:
  166.     st = PARST_ERR;
  167.  
  168. _local_exit:
  169.     if (st != PARST_OK)
  170.     {
  171.         if (inc_name)
  172.             free (inc_name);
  173.     }
  174.     return st;
  175. }
  176. #undef TEXT_BUF_SIZE
  177.  
  178. #define TEXT_BUF_SIZE 15
  179. char get_include_sjasm (const char *s, unsigned *flags, char **name)
  180. {
  181.     char st;
  182.     char buf[TEXT_BUF_SIZE+1];
  183.     const char *endp, *np;
  184.     unsigned sl, nl;
  185.     unsigned inc_flags;
  186.     char *inc_name;
  187.  
  188.     st = PARST_SKIP;
  189.     inc_name = (char *) NULL;
  190.  
  191.     if (!flags || !name)
  192.         goto _error_exit;
  193.  
  194.     // RegEx pattern: [[:space:]]+(include|incbin)[[:space:]]+"[^[:space:]]+"
  195.     // The rest of a line is not analized.
  196.  
  197.     // blanks
  198.     endp = _skip_blanks (s);
  199.     if (s == endp || *endp == '\0')
  200.         goto _skip_line;
  201.     // assembler directive
  202.     s = endp;
  203.     endp = _skip_word (s);
  204.     if (s == endp || *endp == '\0')
  205.         goto _skip_line;
  206.     // (save it)
  207.     sl = endp - s;
  208.     if (sl > TEXT_BUF_SIZE)
  209.         sl = TEXT_BUF_SIZE;
  210.     memcpy (buf, s, sl);
  211.     buf[sl] = '\0';
  212.     // (check it)
  213.     if (!strcasecmp (buf, "incbin"))
  214.         inc_flags = 0;
  215.     else if (!strcasecmp (buf, "include"))
  216.         inc_flags = SRCFL_PARSE;
  217.     else
  218.         goto _skip_line;
  219.     // blanks
  220.     s = endp;
  221.     endp = _skip_blanks (s);
  222.     if (s == endp || *endp == '\0')
  223.         goto _skip_line;
  224.     // string
  225.     s = endp;
  226.     endp = _skip_string (s);
  227.     if (s == endp)
  228.         goto _skip_line;
  229.     // (save it)
  230.     np = s + 1;         // skip opening double quotes character
  231.     nl = endp - s - 2;  // excluding double quotes characters
  232.     inc_name = malloc (nl + 1); // including terminating zero
  233.     if (!inc_name)
  234.     {
  235.         // Fail
  236.         _perror ("malloc");
  237.         goto _error_exit;
  238.     }
  239.     memcpy (inc_name, np, nl);
  240.     inc_name[nl] = '\0';
  241.     // (done)
  242.     st = PARST_OK;
  243.     *flags = inc_flags;
  244.     *name = inc_name;
  245.     goto _local_exit;
  246.  
  247. _skip_line:
  248.     st = PARST_SKIP;
  249.     goto _local_exit;
  250.  
  251. _error_exit:
  252.     st = PARST_ERR;
  253.  
  254. _local_exit:
  255.     if (st != PARST_OK)
  256.     {
  257.         if (inc_name)
  258.             free (inc_name);
  259.     }
  260.     return st;
  261. }
  262. #undef TEXT_BUF_SIZE
  263.  
  264. const struct
  265. {
  266.     get_include_proc_t *proc;
  267.     unsigned syntax;
  268. }
  269. include_procs[] =
  270. {
  271.     { get_include_tasm, SYNTAX_TASM },
  272.     { get_include_sjasm, SYNTAX_SJASM },
  273.     { NULL, 0 }
  274. };
  275.  
  276. bool _find_get_include_proc (unsigned syntax, get_include_proc_t **proc)
  277. {
  278.     unsigned i;
  279.     for (i = 0; include_procs[i].proc; i++)
  280.     {
  281.         if (include_procs[i].syntax == syntax)
  282.         {
  283.             *proc = include_procs[i].proc;
  284.             return true;
  285.         }
  286.     }
  287.     return false;
  288. }
  289.