Thread overview
port of redo-c to BetterC
Jun 09, 2021
aquaratixc
Jun 09, 2021
Imperatorn
Jun 09, 2021
jfondren
Jun 10, 2021
aquaratixc
Jun 10, 2021
Dennis
Jun 10, 2021
aquaratixc
Jun 10, 2021
Dennis
Jun 10, 2021
aquaratixc
June 09, 2021

Good day! This is my first time working with betterC and for the sake of experiment I decided to translate the redo-c implementation (https://github.com/leahneukirchen/redo-c) into BetterC, but I ran into a number of problems:

  1. In the original implementation, there are places where the openat function is used (dir_fd, target, O_RDONLY | O_DIRECTORY); and I couldn't find a replacement. Are there any options where you can get it?
  2. Similarly, the dprintf function was not found, which, as I understand it, is a non-standard extension. Is there a way to add this?
    I will also be glad if someone picks up the idea and brings it to mind. The current version is here: https://github.com/aquaratixc/redo-d/tree/main
June 09, 2021

On Wednesday, 9 June 2021 at 21:45:33 UTC, aquaratixc wrote:

>

Good day! This is my first time working with betterC and for the sake of experiment I decided to translate the redo-c implementation (https://github.com/leahneukirchen/redo-c) into BetterC, but I ran into a number of problems:

  1. In the original implementation, there are places where the openat function is used (dir_fd, target, O_RDONLY | O_DIRECTORY); and I couldn't find a replacement. Are there any options where you can get it?
  2. Similarly, the dprintf function was not found, which, as I understand it, is a non-standard extension. Is there a way to add this?
    I will also be glad if someone picks up the idea and brings it to mind. The current version is here: https://github.com/aquaratixc/redo-d/tree/main

https://dlang.org/spec/interfaceToC.html

June 09, 2021

On Wednesday, 9 June 2021 at 21:45:33 UTC, aquaratixc wrote:

>
  1. In the original implementation, there are places where the openat function is used (dir_fd, target, O_RDONLY | O_DIRECTORY); and I couldn't find a replacement. Are there any options where you can get it?
  2. Similarly, the dprintf function was not found, which, as I understand it, is a non-standard extension. Is there a way to add this?

In general you can just use the C functions directly, with reference to system
manpages, prior interfaces in D repositories (dmd+phobos+druntime are good
repos to have around), https://dlang.org/spec/interfaceToC.html , and (until
ImportC lands) your system's headers for the right magic numbers.

extern(C) nothrow @nogc int dprintf(int fd, scope const char* format, ...);
extern(C) nothrow @nogc int openat(int dirfd, scope const char *pathname, int flags);
extern(C) nothrow @nogc int openat(int dirfd, scope const char *pathname, int flags, int mode);
extern(C) nothrow @nogc int close(int fd);
import core.sys.posix.fcntl : AT_FDCWD, O_RDONLY;
enum O_DIRECTORY = 0x10000;
import std.stdio : File, write;

void main() {
    int dir, file;
    if (-1 != (dir = openat(AT_FDCWD, "test", O_DIRECTORY | O_RDONLY))) {
        scope(exit) close(dir);
        if (-1 != (file = openat(dir, "x", O_RDONLY))) {
            File f;
            f.fdopen(file, "r");
            write("test/x contained: ", f.readln);
        }
    }
}
June 10, 2021

Thank you very much to everyone who answered. That helped. I have more questions ... I also ran into this: there is a function redo_ifchange (int targetc, char ** targetv) inside which the char [targetc] skip; array is defined; , and as a result we get an error like redo.d (784): Error: variable `targetc` cannot be read at compile time. it is clear that the compiler cannot define a variable at the compilation stage and set the dimension from it, but how to solve the question in

June 10, 2021

On Thursday, 10 June 2021 at 09:53:36 UTC, aquaratixc wrote:

>

there is a function redo_ifchange (int targetc, char ** targetv) inside which the char [targetc] skip; array is defined;

That's a Variable-length array which D doesn't support.
If targetc has an upper bound, you can use a static array instead:

import core.stdc.stdlib;

void redo_ifchange (int targetc, char ** targetv) {
    char[4096] buf = void;
    assert(targetc <= buf.length);
    char* skip = buf.ptr;
    // code
}

For larger sizes, you can use heap-allocation:

import core.stdc.stdlib;

void redo_ifchange (int targetc, char ** targetv) {
    char* skip = cast(char*) malloc(targetc * char.sizeof);
    scope(exit) free(skip);
    // code
}

And if you really want variable-size stack allocation, you can use alloca:

import core.stdc.stdlib;

void redo_ifchange (int targetc, char ** targetv) {
    char* skip = cast(char*) alloca(targetc * char.sizeof);
    // code
}

Though I don't recommend it.

June 10, 2021

On Thursday, 10 June 2021 at 10:04:38 UTC, Dennis wrote:

>

On Thursday, 10 June 2021 at 09:53:36 UTC, aquaratixc wrote:

>

there is a function redo_ifchange (int targetc, char ** targetv) inside which the char [targetc] skip; array is defined;

That's a Variable-length array which D doesn't support.
If targetc has an upper bound, you can use a static array instead:

import core.stdc.stdlib;

void redo_ifchange (int targetc, char ** targetv) {
    char[4096] buf = void;
    assert(targetc <= buf.length);
    char* skip = buf.ptr;
    // code
}

For larger sizes, you can use heap-allocation:

import core.stdc.stdlib;

void redo_ifchange (int targetc, char ** targetv) {
    char* skip = cast(char*) malloc(targetc * char.sizeof);
    scope(exit) free(skip);
    // code
}

And if you really want variable-size stack allocation, you can use alloca:

import core.stdc.stdlib;

void redo_ifchange (int targetc, char ** targetv) {
    char* skip = cast(char*) alloca(targetc * char.sizeof);
    // code
}

Though I don't recommend it.

Thanks. Its really helpful. However, as I said, there are still questions: in particular, there is one mistake that I could not resolve. When I try to copy, I get an error like this: redo.o:redo.d:function _D4redo13redo_ifchangeFiPPaZv: error: undefined reference to '_D4core3sys5posixQk4wait9WIFEXITEDFNaNbNiNfiZb' redo.o:redo.d:function _D4redo13redo_ifchangeFiPPaZv: error: undefined reference to '_D4core3sys5posixQk4wait11WEXITSTATUSFNaNbNiNfiZi' collect2: although i imported core.sys.posix.sys.wait

June 10, 2021

On Thursday, 10 June 2021 at 10:23:00 UTC, aquaratixc wrote:

>

Thanks. Its really helpful. However, as I said, there are still questions: in particular, there is one mistake that I could not resolve. When I try to copy, I get an error like this: redo.o:redo.d:function _D4redo13redo_ifchangeFiPPaZv: error: undefined reference to '_D4core3sys5posixQk4wait9WIFEXITEDFNaNbNiNfiZb' redo.o:redo.d:function _D4redo13redo_ifchangeFiPPaZv: error: undefined reference to '_D4core3sys5posixQk4wait11WEXITSTATUSFNaNbNiNfiZi' collect2: although i imported core.sys.posix.sys.wait

WIFEXITED and WEXITSTATUS are C macros that druntime translates to D functions.
Importing only means you expect it to be there at link-time. When compiling with -betterC, you don't actually link druntime usually. I think it's easiest to just copy-paste those function definitions from druntime to your own source instead of importing them. Or you can compile with optimizations (e.g. -inline for dmd, -O1 for GDC/LDC) and hope the functions get inlined.

June 10, 2021
On 6/10/21 7:21 AM, Dennis wrote:
> On Thursday, 10 June 2021 at 10:23:00 UTC, aquaratixc wrote:
>> Thanks. Its really helpful. However, as I said, there are still questions: in particular, there is one mistake that I could not resolve. When I try to copy, I get an error like this: ```
>> redo.o:redo.d:function _D4redo13redo_ifchangeFiPPaZv: error: undefined reference to '_D4core3sys5posixQk4wait9WIFEXITEDFNaNbNiNfiZb'
>> redo.o:redo.d:function _D4redo13redo_ifchangeFiPPaZv: error: undefined reference to '_D4core3sys5posixQk4wait11WEXITSTATUSFNaNbNiNfiZi'
>> collect2: ``` although i imported ```core.sys.posix.sys.wait```
> 
> WIFEXITED and WEXITSTATUS are C macros that druntime translates to D functions.
> Importing only means you expect it to be there at link-time. When compiling with `-betterC`, you don't actually link druntime usually. I think it's easiest to just copy-paste those function definitions from druntime to your own source instead of importing them. Or you can compile with optimizations (e.g. `-inline` for dmd, `-O1` for GDC/LDC) and hope the functions get inlined.

Hm... those probably should be marked pragma(inline, true), but I'm not sure if that will be a complete fix.

-Steve
June 10, 2021

Thank you all for your help. I translated the program, and it seems I even collected it with the help of the LDC. I understand the reasons for Segfault, the project is here: https://github.com/aquaratixc/redo-d/blob/main/redo.d