Neat-Lang / neat

The Neat Language compiler. Early beta?
BSD 3-Clause "New" or "Revised" License
111 stars 9 forks source link

Can't use sockets because glibc requires recursive header import #27

Closed dbohdan closed 1 year ago

dbohdan commented 1 year ago

I am trying to translate the following C code to Neat:

#include <netinet/in.h>
#include <sys/socket.h>

void main() {
    struct sockaddr_in serv;
    serv.sin_family = AF_INET;
}

I can't access AF_INET with import c_header("sys/socket.h");. I guess this is because on Linux with glibc it is defined in bits/socket.h instead, which sys/socket.h includes. This a problem in Neat, sincebits/socket.h prevents you from importing it directly. import c_header("bits/socket.h"); results in a GCC error during compilation.

$ gcc -dD -E .obj/cimport.bits_socket_h.h > .obj/cimport.bits_socket_h.h.out
In file included from .obj/cimport.bits_socket_h.h:1:
/usr/include/x86_64-linux-gnu/bits/socket.h:23:3: error: #error "Never include <bits/socket.h> directly; use <sys/socket.h> instead."
   23 | # error "Never include <bits/socket.h> directly; use <sys/socket.h> instead."
      |   ^~~~~
In file included from /usr/include/x86_64-linux-gnu/bits/socket.h:38,
                 from .obj/cimport.bits_socket_h.h:1:
/usr/include/x86_64-linux-gnu/bits/socket_type.h:20:3: error: #error "Never include <bits/socket_type.h> directly; use <sys/socket.h> instead."
   20 | # error "Never include <bits/socket_type.h> directly; use <sys/socket.h> instead."
      |   ^~~~~
command failed with 256
Assertion failed! Aborting.

The compiler then acts like it's compiled the import but still can't use the constant.

Test file:

module socket_test;

macro import std.macro.cimport;

import c_header("netinet/in.h");
import c_header("bits/socket.h");
import c_header("sys/socket.h");

void main(string[] args) {
    mut sockaddr_in serv;
    serv.sin_family = AF_INET;
}

Error:

socket_test.nt:11:
    serv.sin_family = AF_INET;
                      ~~~~~~~ 'AF_INET' not found

Additionally, if I remove AF_INET, I get the following error, probably for similar reasons?

Test file:

module socket_test;

macro import std.macro.cimport;

import c_header("netinet/in.h");

void main(string[] args) {
    mut sockaddr_in serv;
    serv.sin_family = 2;
}

Error:

socket_test.nt:9:
    serv.sin_family = 2;
         ~~~~~~~~~~ sockaddr_in: no such field 'sin_family'
FeepingCreature commented 1 year ago

That's a bug in the C importer; "sys/socket.h" should definitely work. Lemme look into it.

FeepingCreature commented 1 year ago

Okay, AF_INET added. sin_family won't work, because sockaddr_in won't work; the definition is "a bit complicated". Manually declare struct sockaddr_in for now.

FeepingCreature commented 1 year ago
module socket_test;

macro import std.macro.cimport;

import c_header("netinet/in.h");
import c_header("sys/socket.h");

void main(string[] args) {
    mut sockaddr_in serv;
    serv.sin_family = AF_INET;
}

struct sockaddr_in
{
    sa_family_t sin_family;
    in_port_t sin_port;
    in_addr sin_addr;
    // that's what it is on my system
    Vector(ubyte, 8) sin_zero;
}
FeepingCreature commented 1 year ago

Closing as WONTFIX, but reopen if this is something that you need strongly/feel strongly about.