Edit

kc3-lang/kc3/ikc3/ikc3.c

Branch :

  • ikc3/ikc3.c
  • /* kc3
     * Copyright 2022,2023,2024 kmx.io <contact@kmx.io>
     *
     * Permission is hereby granted to use this software granted the above
     * copyright notice and this permission paragraph are included in all
     * copies and substantial portions of this software.
     *
     * THIS SOFTWARE IS PROVIDED "AS-IS" WITHOUT ANY GUARANTEE OF
     * PURPOSE AND PERFORMANCE. IN NO EVENT WHATSOEVER SHALL THE
     * AUTHOR BE CONSIDERED LIABLE FOR THE USE AND PERFORMANCE OF
     * THIS SOFTWARE.
     */
    #include <errno.h>
    #include <string.h>
    #include "../libkc3/kc3.h"
    #include "config.h"
    
    #if HAVE_WINEDITLINE
    # include "buf_wineditline.h"
    #else
    # include "buf_linenoise.h"
    #endif
    
    #define BUFSZ 0x10000
    
    int usage (char *argv0);
    
    sw buf_ignore_character (s_buf *buf)
    {
      u8 b;
      character c = 0;
      sw csize;
      sw r;
      if ((r = buf_peek_character_utf8(buf, &c)) > 0)
        csize = r;
      else if ((r = buf_peek_u8(buf, &b)) > 0)
        csize = 1;
      else
        return r;
      if ((r = buf_ignore(buf, csize)) < 0)
        return r;
      return csize;
    }
    
    sw ikc3_run (void)
    {
      s_tag input;
      sw r;
      s_tag result;
      while (1) {
        r = buf_ignore_spaces(&g_kc3_env.in);
        if (r < 0)
          return 0;
        r = buf_parse_comments(&g_kc3_env.in);
        if (r < 0)
          return 0;
        r = buf_parse_tag(&g_kc3_env.in, &input);
        if (r > 0) {
          if (! eval_tag(&input, &result)) {
            tag_clean(&input);
            continue;
          }
          if (buf_inspect_tag(&g_kc3_env.out, &result) < 0) {
    	tag_clean(&input);
    	tag_clean(&result);
            return 0;
          }
          tag_clean(&input);
          tag_clean(&result);
        }
        if (r < 0)
          return 0;
        if ((r = buf_write_1(&g_kc3_env.out, "\n")) < 0)
          return 0;
        if ((r = buf_flush(&g_kc3_env.out)) < 0)
          return 0;
        if (r < 0 ||
            (r == 0 &&
             (r = buf_ignore_character(&g_kc3_env.in)) <= 0))
          return 0;
      }
      return 0;
    }
    
    int main (int argc, char **argv)
    {
      sw     e = 0;
      s_env *env;
      s_tag *file_dir;
      s_tag  file_dir_save;
      s_tag *file_path;
      s_tag  file_path_save;
      FILE *fp = 0;
      char  in_data[BUF_SIZE];
      s_buf in_original;
      sw r;
      if (argc < 1)
        return usage("ikc3");
      if (! kc3_init(NULL, &argc, &argv))
        return 1;
      env = &g_kc3_env;
      in_original = env->in;
      buf_init(&env->in, false, sizeof(in_data), in_data);
      while (argc) {
        if (! strcmp("--load", *argv) ||
            ! strcmp("-l", *argv)) {
          if (argc < 2) {
            err_write_1(env->argv[0]);
            err_write_1(": ");
            err_write_1(*argv);
            err_write_1(" without an argument\n");
            assert(! "env_init: -l or --load without an argument");
            r = 1;
            goto clean;
          }
          fp = file_open(argv[1], "rb");
          if (! fp) {
            e = errno;
            err_write_1("ikc3: ");
            err_write_1(argv[1]);
            err_write_1(": ");
            err_write_1(strerror(e));
            err_write_1("\n");
            assert(! "ikc3: fopen");
            r = 1;
            goto clean;
          }
          if (! buf_file_open_r(&env->in, fp)) {
            r = -1;
            goto clean;
          }
          file_dir = frame_get_w(&env->global_frame, &g_sym___DIR__);
          file_dir_save = *file_dir;
          file_path = frame_get_w(&env->global_frame, &g_sym___FILE__);
          file_path_save = *file_path;
          tag_init_str_1(file_path, NULL, argv[1]);
          file_dir->type = TAG_STR;
          if (! file_dirname(&file_path->data.str, &file_dir->data.str)) {
            buf_file_close(&env->in);
            r = -1;
            goto clean;
          }
          r = ikc3_run();
          *file_dir = file_dir_save;
          *file_path = file_path_save;
          buf_file_close(&env->in);
          fclose(fp);
          if (r)
            goto clean;
          argc -= 2;
          argv += 2;
        }
        else if (argc == 1 && ! strcmp("--quit", *argv)) {
          r = 0;
          goto clean;
        }
        else
          break;
      }
    #if HAVE_WINEDITLINE
      buf_wineditline_open_r(&env->in, "ikc3> ", ".ikc3_history");
    #else
      buf_linenoise_open_r(&env->in, "ikc3> ", ".ikc3_history");
    #endif
      r = ikc3_run();
    #if HAVE_WINEDITLINE
      buf_wineditline_close(&env->in, ".ikc3_history");
    #else
      buf_linenoise_close(&env->in, ".ikc3_history");
    #endif
     clean:
      env->in = in_original;
      kc3_clean(NULL);
      return r;
    }
    
    int usage (char *argv0)
    {
      printf("Usage: %s [--load FILE] [--quit]\n", argv0);
      return 1;
    }