~andyc/oil

5f192df1c6f8b818fc8e9c24f19a36fd4ddd4478 — Andy C 2 months ago f819984
[refactor] Combine small files in cpp/leaky_stdlib.{h,cc}

- fcntl
- posix
- time_

Add cpp/README.md

Also rename to cpp/leaky_pgen2.{cc,h}
13 files changed, 162 insertions(+), 131 deletions(-)

M cpp/NINJA_subgraph.py
A cpp/README.md
M cpp/leaky_binding_test.cc
M cpp/leaky_core.cc
D cpp/leaky_fcntl_.cc
D cpp/leaky_fcntl_.h
R cpp/{leaky_pgen2_parse.cc => leaky_pgen2.cc}
R cpp/{leaky_pgen2_parse.h => leaky_pgen2.h}
M cpp/leaky_preamble.h
R cpp/{leaky_posix.cc => leaky_stdlib.cc}
R cpp/{leaky_posix.h => leaky_stdlib.h}
D cpp/leaky_time_.h
M cpp/test.sh
M cpp/NINJA_subgraph.py => cpp/NINJA_subgraph.py +3 -4
@@ 37,7 37,7 @@ _build/   # input source

  preprocessed/
    cxx-dbg/
      leaky_posix.cc
      leaky_stdlib.cc
    cxx-dbg.txt  # line counts




@@ 84,11 84,10 @@ DEPS_CC = [
    'cpp/leaky_frontend_match.cc',
    'cpp/leaky_frontend_tdop.cc',
    'cpp/leaky_osh.cc',
    'cpp/leaky_pgen2_parse.cc',
    'cpp/leaky_pgen2.cc',
    'cpp/leaky_pylib.cc',
    'cpp/leaky_dumb_alloc.cc',
    'cpp/leaky_fcntl_.cc',
    'cpp/leaky_posix.cc',
    'cpp/leaky_stdlib.cc',
    'cpp/leaky_libc.cc',

    # generated

A cpp/README.md => cpp/README.md +46 -0
@@ 0,0 1,46 @@
cpp/ - Hand-written C++ Code
============================

Structure of this directory:

Correspond to repo directories:

    leaky_core.{cc,h}
    leaky_osh.{cc,h}
      from osh import arith_parse
      from osh import bool_stat

    leaky_pylib.{cc,h}  # Corresponds to pylib/
      from pylib import os_path
      from pylib import path_stat

    leaky_pgen2.{cc,h}
      from pgen2 import parse

    leaky_stdlib.{cc,h}  # Python standard library modules
      import fcntl
      import time
      import posix  # forked in native/posixmodule.c

    qsn.h

Correspond to files:

    leaky_core_error.h    # Straggler for core/error.py
    leaky_core_pyerror.h  # core/pyerror.py

    leaky_libc.{cc,h}  # Corresponds to Python extension native/libc.c

    # These three are separate because there is generated code associated with
    # them, like the re2c lexer.

    leaky_frontend_flag_spec.{cc,h}
      from frontend import flag_spec

    leaky_frontend_match.{cc,h}
      from frontend import match

    leaky_frontend_tdop.{cc,h}
      from frontend import tdop

TODO: We want non-leaky versions of all files!

M cpp/leaky_binding_test.cc => cpp/leaky_binding_test.cc +1 -2
@@ 13,9 13,8 @@
#include "leaky_frontend_match.h"
#include "leaky_libc.h"
#include "leaky_osh.h"
#include "leaky_posix.h"
#include "leaky_stdlib.h"
#include "leaky_pylib.h"
#include "leaky_time_.h"
#include "vendor/greatest.h"

namespace Id = id_kind_asdl::Id;

M cpp/leaky_core.cc => cpp/leaky_core.cc +6 -3
@@ 4,7 4,7 @@
#include "mycpp/myerror.h"
// clang-format on

#include "leaky_core.h"
#include "cpp/leaky_core.h"

#include <errno.h>
#include <pwd.h>  // passwd


@@ 13,9 13,12 @@
#include <sys/times.h>     // tms / times()
#include <sys/utsname.h>   // uname
#include <sys/wait.h>      // waitpid()
#include <time.h>          // time()
#include <unistd.h>        // getuid(), environ

#include "leaky_time_.h"
#include "mycpp/mylib_leaky.h"

using mylib::CopyStr;

namespace pyos {



@@ 158,7 161,7 @@ Tuple3<double, double, double> Time() {
    throw new IOError(errno);
  }

  time_t t = time_::time();
  time_t t = ::time(nullptr);
  auto result = Tuple3<double, double, double>(
      (double)t, (double)ru.ru_utime.tv_sec, (double)ru.ru_stime.tv_sec);
  return result;

D cpp/leaky_fcntl_.cc => cpp/leaky_fcntl_.cc +0 -30
@@ 1,30 0,0 @@
// fcntl_.cc

// clang-format off
#include "mycpp/myerror.h"  // for IOError
// clang-format on

#include "leaky_fcntl_.h"

#include <errno.h>
#include <fcntl.h>  // the system header

namespace fcntl_ {

int fcntl(int fd, int cmd) {
  int result = ::fcntl(fd, cmd);
  if (result < 0) {
    throw new IOError(errno);
  }
  return result;
}

int fcntl(int fd, int cmd, int arg) {
  int result = ::fcntl(fd, cmd, arg);
  if (result < 0) {
    throw new IOError(errno);
  }
  return result;
}

}  // namespace fcntl_

D cpp/leaky_fcntl_.h => cpp/leaky_fcntl_.h +0 -16
@@ 1,16 0,0 @@
// fcntl.h

#ifndef FCNTL_H
#define FCNTL_H

#include <fcntl.h>

namespace fcntl_ {

// for F_GETFD
int fcntl(int fd, int cmd);
int fcntl(int fd, int cmd, int arg);

}  // namespace fcntl_

#endif  // FCNTL_H

R cpp/leaky_pgen2_parse.cc => cpp/leaky_pgen2.cc +2 -2
@@ 1,6 1,6 @@
// pgen2_parse.cc
// leaky_pgen2.cc

#include "leaky_pgen2_parse.h"
#include "leaky_pgen2.h"

namespace parse {


R cpp/leaky_pgen2_parse.h => cpp/leaky_pgen2.h +4 -4
@@ 1,7 1,7 @@
// leaky_pgen2_parse.h
// leaky_pgen2.h

#ifndef PGEN2_PARSE_H
#define PGEN2_PARSE_H
#ifndef LEAKY_PGEN2_H
#define LEAKY_PGEN2_H

#include "_build/cpp/id_kind_asdl.h"
#include "_build/cpp/syntax_asdl.h"


@@ 50,4 50,4 @@ class Parser {

}  // namespace parse

#endif  // PGEN2_PARSE_H
#endif  // LEAKY_PGEN2_H

M cpp/leaky_preamble.h => cpp/leaky_preamble.h +3 -4
@@ 5,6 5,7 @@
// clang-format on

#include <errno.h>
#include <fcntl.h>  // F_DUPFD used directly
#include <sys/wait.h>  // WIFSIGNALED, etc. called DIRECTLY

#include "leaky_dumb_alloc.h"  // change the allocator


@@ 29,16 30,14 @@ using id_kind_asdl::Kind_t;
//#include "core_process.h"
#include "leaky_core.h"
#include "leaky_core_pyerror.h"
#include "leaky_fcntl_.h"
#include "leaky_frontend_flag_spec.h"
#include "leaky_frontend_match.h"
#include "leaky_frontend_tdop.h"
#include "leaky_libc.h"
#include "leaky_osh.h"
#include "leaky_pgen2_parse.h"
#include "leaky_posix.h"
#include "leaky_pgen2.h"
#include "leaky_stdlib.h"
#include "leaky_pylib.h"
#include "leaky_time_.h"
#include "qsn.h"
#include "segfault_handler.h"


R cpp/leaky_posix.cc => cpp/leaky_stdlib.cc +75 -2
@@ 1,18 1,46 @@
// posix.cc: Replacement for native/posixmodule.c
// leaky_stdlib.cc: Replacement for standard library modules
// and native/posixmodule.c

// clang-format off
#include "mycpp/myerror.h"  // for OSError; must come first
// clang-format on

#include "leaky_posix.h"
#include "leaky_stdlib.h"

#include <errno.h>
#include <fcntl.h>      // open
#include <sys/stat.h>   // umask
#include <sys/types.h>  // umask
#include <sys/wait.h>   // WUNTRACED
#include <time.h>
#include <unistd.h>

#include "cpp/leaky_core_error.h"
#include "cpp/leaky_core_pyerror.h"
#include "mycpp/mylib_leaky.h"
using mylib::CopyStr;
using mylib::OverAllocatedStr;

namespace fcntl_ {

int fcntl(int fd, int cmd) {
  int result = ::fcntl(fd, cmd);
  if (result < 0) {
    throw new IOError(errno);
  }
  return result;
}

int fcntl(int fd, int cmd, int arg) {
  int result = ::fcntl(fd, cmd, arg);
  if (result < 0) {
    throw new IOError(errno);
  }
  return result;
}

}  // namespace fcntl_

namespace posix {

int umask(int mask) {


@@ 94,3 122,48 @@ void execve(Str* argv0, List<Str*>* argv, Dict<Str*, Str*>* environ) {
}

}  // namespace posix

namespace time_ {

void tzset() {
  ::tzset();
}

time_t time() {
  return ::time(nullptr);
}

// NOTE(Jesse): time_t is specified to be an arithmetic type by C++. On most
// systems it's a 64-bit integer.  64 bits is used because 32 will overflow in
// 2038.  Someone on a comittee somewhere thought of that when moving to 64-bit
// architectures to prevent breaking ABI again; on 32-bit systems it's usually
// 32 bits.  Point being, using anything but the time_t typedef here could
// (unlikely, but possible) produce weird behavior.
time_t localtime(time_t ts) {
  tm* loc_time = ::localtime(&ts);
  time_t result = mktime(loc_time);
  return result;
}

Str* strftime(Str* s, time_t ts) {
  // TODO: may not work with mylib_leaky.h
  // https://github.com/oilshell/oil/issues/1221
  assert(s->IsNulTerminated());

  tm* loc_time = ::localtime(&ts);

  const int max_len = 1024;
  Str* result = OverAllocatedStr(max_len);
  int n = strftime(result->data(), max_len, s->data_, loc_time);
  if (n == 0) {
    // bash silently truncates on large format string like
    //   printf '%(%Y)T'
    // Oil doesn't mask errors
    // No error location info, but leaving it out points reliably to 'printf'
    e_die(CopyStr("strftime() result exceeds 1024 bytes"));
  }
  result->SetObjLenFromStrLen(n);
  return result;
}

}  // namespace time_

R cpp/leaky_posix.h => cpp/leaky_stdlib.h +21 -4
@@ 1,12 1,20 @@
// leaky_posix.h: Replacement for native/posixmodule.c
// leaky_stdlib.h: Replacement for native/posixmodule.c

#ifndef POSIX_H
#define POSIX_H
#ifndef LEAKY_STDLIB_H
#define LEAKY_STDLIB_H

#include <unistd.h>

#include "mycpp/mylib_leaky.h"

namespace fcntl_ {

// for F_GETFD
int fcntl(int fd, int cmd);
int fcntl(int fd, int cmd, int arg);

}  // namespace fcntl_

namespace posix {

int umask(int mask);


@@ 96,4 104,13 @@ void execve(Str* argv0, List<Str*>* argv, Dict<Str*, Str*>* environ);

}  // namespace posix

#endif  // POSIX_H
namespace time_ {

void tzset();
time_t time();
time_t localtime(time_t ts);
Str* strftime(Str* s, time_t ts);

}  // namespace time_

#endif  // LEAKY_STDLIB_H

D cpp/leaky_time_.h => cpp/leaky_time_.h +0 -59
@@ 1,59 0,0 @@
// time.h

#ifndef TIME_H
#define TIME_H

#include <time.h>

#include "cpp/leaky_core_error.h"
#include "cpp/leaky_core_pyerror.h"
#include "mycpp/mylib_leaky.h"
using mylib::CopyStr;
using mylib::OverAllocatedStr;

namespace time_ {

inline void tzset() {
  ::tzset();
}

inline time_t time() {
  return ::time(nullptr);
}

// NOTE(Jesse): time_t is specified to be an arithmetic type by C++. On most
// systems it's a 64-bit integer.  64 bits is used because 32 will overflow in
// 2038.  Someone on a comittee somewhere thought of that when moving to 64-bit
// architectures to prevent breaking ABI again; on 32-bit systems it's usually
// 32 bits.  Point being, using anything but the time_t typedef here could
// (unlikely, but possible) produce weird behavior.
inline time_t localtime(time_t ts) {
  tm* loc_time = ::localtime(&ts);
  time_t result = mktime(loc_time);
  return result;
}

inline Str* strftime(Str* s, time_t ts) {
  // TODO: may not work with mylib_leaky.h
  // https://github.com/oilshell/oil/issues/1221
  assert(s->IsNulTerminated());

  tm* loc_time = ::localtime(&ts);

  const int max_len = 1024;
  Str* result = OverAllocatedStr(max_len);
  int n = strftime(result->data(), max_len, s->data_, loc_time);
  if (n == 0) {
    // bash silently truncates on large format string like
    //   printf '%(%Y)T'
    // Oil doesn't mask errors
    // No error location info, but leaving it out points reliably to 'printf'
    e_die(CopyStr("strftime() result exceeds 1024 bytes"));
  }
  result->SetObjLenFromStrLen(n);
  return result;
}

}  // namespace time_

#endif  // TIME_H

M cpp/test.sh => cpp/test.sh +1 -1
@@ 56,7 56,7 @@ readonly LEAKY_TEST_SRC=(
    cpp/leaky_frontend_match.cc \
    cpp/leaky_libc.cc \
    cpp/leaky_osh.cc \
    cpp/leaky_posix.cc \
    cpp/leaky_stdlib.cc \
    cpp/leaky_pylib.cc \
    mycpp/mylib_leaky.cc
)