?login_element?

Subversion Repositories NedoOS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /* asmfile.c - assembler file structure.
  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 <errno.h>
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include "debug.h"
  14. #include "l_list.h"
  15. #include "asmfile.h"
  16.  
  17. void _asm_file_reset_pos (struct asm_file_t *self)
  18. {
  19.     self->pos = -1;             // invalid
  20.     self->line = 0;             // invalid
  21.     self->line_start = -1;      // invalid
  22.     self->line_end = -1;        // invalid
  23. }
  24.  
  25. void asm_file_clear (struct asm_file_t *self)
  26. {
  27.     if (!self)
  28.         return; // Fail
  29.     self->data = NULL;
  30.     self->size = 0;
  31.     _asm_file_reset_pos (self);
  32. }
  33.  
  34. // Returns "false" on success.
  35. bool asm_file_load (struct asm_file_t *self, const char *name)
  36. {
  37.     bool ok;
  38.     FILE *f;
  39.     long s;
  40.     char *p;
  41.  
  42.     if (!self)
  43.     {
  44.         // Fail
  45.         errno = EINVAL;
  46.         return false;
  47.     }
  48.  
  49.     ok = false;
  50.     f = NULL;
  51.     s = 0;
  52.     p = NULL;
  53.  
  54.     _DBG_ ("File name = '%s'", name);
  55.  
  56. #if defined (_WIN32) || defined (_WIN64)
  57.     f = fopen (name, "rb");
  58. #else
  59.     f = fopen (name, "r");
  60. #endif
  61.     if (!f)
  62.     {
  63.         // Fail
  64.         _perror ("fopen");
  65.         goto _local_exit;
  66.     }
  67.  
  68.     errno = 0;
  69.  
  70.     fseek (f, 0, SEEK_END);
  71.     if (errno)
  72.     {
  73.         // Fail
  74.         _perror ("fseek");
  75.         goto _local_exit;
  76.     }
  77.  
  78.     s = ftell (f);
  79.     if (s < 0)
  80.     {
  81.         // Fail
  82.         _perror ("ftell");
  83.         goto _local_exit;
  84.     }
  85.  
  86.     fseek (f, 0, SEEK_SET);
  87.     if (errno)
  88.     {
  89.         // Fail
  90.         _perror ("fseek");
  91.         goto _local_exit;
  92.     }
  93.  
  94.     _DBG_ ("File size = %li", (long) s);
  95.  
  96.     if (s)
  97.     {
  98.         p = malloc (s);
  99.         if (!p)
  100.         {
  101.             // Fail
  102.             _perror ("malloc");
  103.             goto _local_exit;
  104.         }
  105.         errno = 0;
  106.         if (fread (p, s, 1, f) != 1)
  107.         {
  108.             // Fail
  109.             _perror ("fread");
  110.             goto _local_exit;
  111.         }
  112.         // Success
  113.         ok = true;
  114.     }
  115.  
  116. _local_exit:
  117.     if (f)
  118.         fclose (f);
  119.     if (!ok)
  120.     {
  121.         if (p)
  122.             free (p);
  123.         p = NULL;
  124.         s = 0;
  125.     }
  126.     self->data = p;
  127.     self->size = s;
  128.     _asm_file_reset_pos (self);
  129.     return ok;
  130. }
  131.  
  132. bool asm_file_eof (struct asm_file_t *self)
  133. {
  134.     if (!self)
  135.     {
  136.         // Fail
  137.         errno = EINVAL;
  138.         return true;
  139.     }
  140.     if (self->size)
  141.     {
  142.         // Success
  143.         if (0         <= self->pos
  144.         &&  self->pos <  self->size)
  145.             return false;
  146.         else
  147.             return true;
  148.     }
  149.     else
  150.     {
  151.         // Fail
  152.         errno = ENOENT;
  153.         return true;
  154.     }
  155. }
  156.  
  157. bool asm_file_eol (struct asm_file_t *self)
  158. {
  159.     if (!self)
  160.     {
  161.         // Fail
  162.         errno = EINVAL;
  163.         return true;
  164.     }
  165.     if (!asm_file_eof (self))
  166.     {
  167.         // Success
  168.         if (self->line_start <= self->pos
  169.         &&  self->pos        <= self->line_end)
  170.             return false;
  171.         else
  172.             return true;
  173.     }
  174.     else
  175.         return true;    // Fail
  176. }
  177.  
  178. const char *_find_line_end (const char *s, unsigned len)
  179. {
  180.     if (!s)
  181.         return (char *) NULL;   // Fail
  182.     while (len)
  183.     {
  184.         if (len && (*s == '\r' || *s == '\n'))
  185.             break;
  186.         s++;
  187.         len--;
  188.     }
  189.     return s;   // Success
  190. }
  191.  
  192. const char *_skip_line_end (const char *s, unsigned len)
  193. {
  194.     if (!s)
  195.         return (char *) NULL;   // Fail
  196.     if (len)
  197.     {
  198.         if (*s == '\r')
  199.         {
  200.             // found
  201.             len--;
  202.             s++;
  203.             if (len && *s == '\n')
  204.                 s++;
  205.         }
  206.         else if (*s == '\n')
  207.         {
  208.             // found
  209.             len--;
  210.             s++;
  211.             if (len && *s == '\r')
  212.                 s++;
  213.         }
  214.         else
  215.             s += len;   // not found, skip to the end
  216.     }
  217.     return s;
  218. }
  219.  
  220. bool asm_file_next_line (struct asm_file_t *self, const char **s, unsigned *len)
  221. {
  222.     const char *startp, *endp;
  223.     unsigned sz;
  224.  
  225.     if (!self || !s || !len)
  226.     {
  227.         // Fail
  228.         errno = EINVAL;
  229.         return false;
  230.     }
  231.     if (self->pos < 0 || (self->pos >= 0 && !asm_file_eof (self)))
  232.     {
  233.         if (self->pos < 0)
  234.         {
  235.             // Start reading
  236.             sz = self->size;
  237.             startp = self->data;
  238.         }
  239.         else
  240.         {
  241.             // Continue reading
  242.             sz = self->size - self->line_end;
  243.             startp = _skip_line_end (self->data + self->line_end, sz);
  244.             self->pos = startp - self->data;
  245.             sz = self->size - self->pos;
  246.         }
  247.         endp = _find_line_end (startp, sz);
  248.         self->pos = startp - self->data;
  249.         if (!asm_file_eof (self))
  250.         {
  251.             // Success
  252.             self->line++;
  253.             self->line_start = self->pos;
  254.             self->line_end = endp - self->data;
  255.             *s = self->data + self->line_start;
  256.             *len = self->line_end - self->line_start;
  257.             return true;
  258.         }
  259.     }
  260.     // Fail
  261.     self->line_start = self->pos;
  262.     self->line_end = self->pos;
  263.     *s = (char *) NULL;
  264.     *len = 0;
  265.     return false;
  266. }
  267.  
  268. void asm_file_free (struct asm_file_t *self)
  269. {
  270.     if (!self)
  271.     {
  272.         // Fail
  273.         errno = EINVAL;
  274.         return;
  275.     }
  276.     if (self->data)
  277.         free (self->data);
  278.     asm_file_clear (self);
  279. }
  280.