DNS query: Difference between revisions

m
→‎{{header|Phix}}: added syntax colouring, marked p2js incompatible
(Added Wren)
m (→‎{{header|Phix}}: added syntax colouring, marked p2js incompatible)
Line 1,069:
Translated from C/MSDN/several man pages.<br>
<b>NB:</b> may warrant further testing, see output.
<!--<lang Phix>include builtins\cffi.e(notonline)-->
<span style="color: #008080;">without</span> <span style="color: #008080;">js</span>
 
<span style="color: #008080;">include</span> <span style="color: #000000;">builtins</span><span style="color: #0000FF;">\</span><span style="color: #000000;">cffi</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
constant AF_UNSPEC = 0,
-- AF_INET = 2,
<span style="color: #008080;">constant</span> <span style="color: #000000;">AF_UNSPEC</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span>
-- AF_INET6 = 23,
<span style="color: #000080;font-style:italic;">-- AF_INET = 2,
-- SOCK_STREAM = 1,
-- SOCK_DGRAMAF_INET6 = 223,
-- IPPROTO_TCPSOCK_STREAM = 61,</span>
<span style="color: #000000;">SOCK_DGRAM</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">,</span>
NI_MAXHOST = 1025,
<span style="color: #000080;font-style:italic;">-- IPPROTO_TCP = 6,</span>
NI_NUMERICHOST = iff(platform()=LINUX?1:2)
<span style="color: #000000;">NI_MAXHOST</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1025</span><span style="color: #0000FF;">,</span>
 
<span style="color: #000000;">NI_NUMERICHOST</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">platform</span><span style="color: #0000FF;">()=</span><span style="color: #004600;">LINUX</span><span style="color: #0000FF;">?</span><span style="color: #000000;">1</span><span style="color: #0000FF;">:</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)</span>
constant tWAD = """
typedef struct WSAData {
<span style="color: #008080;">constant</span> <span style="color: #000000;">tWAD</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"""
WORD wVersion;
typedef struct WSAData {
WORD wHighVersion;
char WORD szDescription[257] wVersion;
char WORD szSystemStatus[129] wHighVersion;
char szDescription[257];
unsigned short iMaxSockets;
char szSystemStatus[129];
unsigned short iMaxUdpDg;
unsigned short iMaxSockets;
char *lpVendorInfo;
unsigned short iMaxUdpDg;
} WSADATA, *LPWSADATA;
char *lpVendorInfo;
""",
} WSADATA, *LPWSADATA;
tWAS = """
"""</span><span style="color: #0000FF;">,</span>
int WSAStartup(
<span style="color: #000000;">tWAS</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"""
_In_ WORD wVersionRequested,
int WSAStartup(
_Out_ LPWSADATA lpWSAData
_In_ WORD wVersionRequested,
);
_Out_ LPWSADATA lpWSAData
""",
);
tWAC = """
"""</span><span style="color: #0000FF;">,</span>
int WSACleanup(void);
<span style="color: #000000;">tWAC</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"""
""",
int WSACleanup(void);
tAI_W="""
"""</span><span style="color: #0000FF;">,</span>
typedef struct addrinfo {
<span style="color: #000000;">tAI_W</span><span style="color: #0000FF;">=</span><span style="color: #008000;">"""
int ai_flags;
typedef struct addrinfo {
int ai_family;
int ai_socktypeai_flags;
int ai_protocolai_family;
size_t int ai_addrlen ai_socktype;
char int *ai_canonname ai_protocol;
size_t ai_addrlen;
struct sockaddr *ai_addr;
char *ai_canonname;
struct addrinfo *ai_next;
struct sockaddr *ai_addr;
} ADDRINFOA, *PADDRINFOA;
struct addrinfo *ai_next;
""",
} ADDRINFOA, *PADDRINFOA;
tAI_L="""
"""</span><span style="color: #0000FF;">,</span>
typedef struct addrinfo {
<span style="color: #000000;">tAI_L</span><span style="color: #0000FF;">=</span><span style="color: #008000;">"""
int ai_flags;
typedef struct addrinfo {
int ai_family;
int ai_socktypeai_flags;
int ai_protocolai_family;
int ai_addrlenai_socktype;
int ai_protocol;
struct sockaddr *ai_addr;
char int *ai_canonname ai_addrlen;
struct addrinfosockaddr *ai_nextai_addr;
char *ai_canonname;
};
struct addrinfo *ai_next;
""",
};
tGAI = """
"""</span><span style="color: #0000FF;">,</span>
int getaddrinfo(
<span style="color: #000000;">tGAI</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"""
_In_opt_ PCSTR pNodeName,
int getaddrinfo(
_In_opt_ PCSTR pServiceName,
_In_opt_ PCSTR pNodeName,
_In_opt_ const ADDRINFOA *pHints,
_In_opt_ PCSTR pServiceName,
_Out_ PADDRINFOA *ppResult
_In_opt_ const ADDRINFOA *pHints,
);
_Out_ PADDRINFOA *ppResult
""",
);
--int getaddrinfo(const char *node, const char *service,
"""</span><span style="color: #0000FF;">,</span>
-- const struct addrinfo *hints,
<span style="color: #000080;font-style:italic;">--int getaddrinfo(const char *node, const char *service,
-- struct addrinfo **res);
-- const struct addrinfo *hints,
tGNI = """
-- struct addrinfo **res);</span>
int getnameinfo(
<span style="color: #000000;">tGNI</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"""
_In_ sockaddr *sa,
int getnameinfo(
_In_ int salen,
_Out_ _In_ char sockaddr *hostsa,
_In_ DWORDint hostlensalen,
_Out_ char *servhost,
_In_ DWORD servlenhostlen,
_In_ _Out_ intchar flags*serv,
_In_ DWORD servlen,
);
_In_ int flags
""",
);
--int getnameinfo(const struct sockaddr *addr, socklen_t addrlen,
"""</span><span style="color: #0000FF;">,</span>
-- char *host, socklen_t hostlen,
<span style="color: #000080;font-style:italic;">--int getnameinfo(const struct sockaddr *addr, socklen_t addrlen,
-- char *serv, socklen_t servlen, int flags);
-- char *host, socklen_t hostlen,
tFAI = """
-- char *serv, socklen_t servlen, int flags);</span>
void freeaddrinfo(
<span style="color: #000000;">tFAI</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"""
_In_ struct addrinfo *ai
void freeaddrinfo(
);
_In_ struct addrinfo *ai
"""
);
--void freeaddrinfo(struct addrinfo *res);
"""</span>
 
<span style="color: #000080;font-style:italic;">--void freeaddrinfo(struct addrinfo *res);</span>
integer xgetaddrinfo = NULL, xgetnameinfo, xfreeaddrinfo, idAI,
xwsastartup, xwsacleanup, error
<span style="color: #004080;">integer</span> <span style="color: #000000;">xgetaddrinfo</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">NULL</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">xgetnameinfo</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">xfreeaddrinfo</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">idAI</span><span style="color: #0000FF;">,</span>
 
<span style="color: #000000;">xwsastartup</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">xwsacleanup</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">error</span>
function get_name_info(string fqdn)
if xgetaddrinfo=NULL then
<span style="color: #008080;">function</span> <span style="color: #000000;">get_name_info</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">fqdn</span><span style="color: #0000FF;">)</span>
atom lib
<span style="color: #008080;">if</span> <span style="color: #000000;">xgetaddrinfo</span><span style="color: #0000FF;">=</span><span style="color: #004600;">NULL</span> <span style="color: #008080;">then</span>
if platform()=WINDOWS then
<span style="color: #004080;">atom</span> <span style="color: #000000;">lib</span>
integer idWAD = define_struct(tWAD)
<span style="color: #008080;">if</span> <span style="color: #7060A8;">platform</span><span style="color: #0000FF;">()=</span><span style="color: #004600;">WINDOWS</span> <span style="color: #008080;">then</span>
atom pWAD = allocate_struct(idWAD,cleanup:=true)
<span style="color: #004080;">integer</span> <span style="color: #000000;">idWAD</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">define_struct</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tWAD</span><span style="color: #0000FF;">)</span>
lib = open_dll("Ws2_32.dll")
<span style="color: #004080;">atom</span> <span style="color: #000000;">pWAD</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">allocate_struct</span><span style="color: #0000FF;">(</span><span style="color: #000000;">idWAD</span><span style="color: #0000FF;">,</span><span style="color: #000000;">cleanup</span><span style="color: #0000FF;">:=</span><span style="color: #004600;">true</span><span style="color: #0000FF;">)</span>
xwsastartup = define_cffi_func(lib,tWAS)
<span style="color: #000000;">lib</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">open_dll</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Ws2_32.dll"</span><span style="color: #0000FF;">)</span>
xwsacleanup = define_cffi_func(lib,tWAC)
<span style="color: #000000;">xwsastartup</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">define_cffi_func</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lib</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tWAS</span><span style="color: #0000FF;">)</span>
error = c_func(xwsastartup,{#00020002,pWAD})
<span style="color: #000000;">xwsacleanup</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">define_cffi_func</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lib</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tWAC</span><span style="color: #0000FF;">)</span>
if error then ?9/0 end if
<span style="color: #000000;">error</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">c_func</span><span style="color: #0000FF;">(</span><span style="color: #000000;">xwsastartup</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">#00020002</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pWAD</span><span style="color: #0000FF;">})</span>
idAI = define_struct(tAI_W)
<span style="color: #008080;">if</span> <span style="color: #000000;">error</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
elsif platform()=LINUX then
<span style="color: #000000;">idAI</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">define_struct</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tAI_W</span><span style="color: #0000FF;">)</span>
lib = open_dll("libc.so.6")
<span style="color: #008080;">elsif</span> <span style="color: #7060A8;">platform</span><span style="color: #0000FF;">()=</span><span style="color: #004600;">LINUX</span> <span style="color: #008080;">then</span>
idAI = define_struct(tAI_L)
<span style="color: #000000;">lib</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">open_dll</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"libc.so.6"</span><span style="color: #0000FF;">)</span>
end if
<span style="color: #000000;">idAI</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">define_struct</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tAI_L</span><span style="color: #0000FF;">)</span>
xgetaddrinfo = define_cffi_func(lib,tGAI)
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
xgetnameinfo = define_cffi_func(lib,tGNI)
<span style="color: #000000;">xgetaddrinfo</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">define_cffi_func</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lib</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tGAI</span><span style="color: #0000FF;">)</span>
xfreeaddrinfo = define_cffi_proc(lib,tFAI)
<span style="color: #000000;">xgetnameinfo</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">define_cffi_func</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lib</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tGNI</span><span style="color: #0000FF;">)</span>
end if
<span style="color: #000000;">xfreeaddrinfo</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">define_cffi_proc</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lib</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tFAI</span><span style="color: #0000FF;">)</span>
atom hints = allocate_struct(idAI,cleanup:=true),
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
res = allocate(machine_word(),cleanup:=true),
<span style="color: #004080;">atom</span> <span style="color: #000000;">hints</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">allocate_struct</span><span style="color: #0000FF;">(</span><span style="color: #000000;">idAI</span><span style="color: #0000FF;">,</span><span style="color: #000000;">cleanup</span><span style="color: #0000FF;">:=</span><span style="color: #004600;">true</span><span style="color: #0000FF;">),</span>
host = allocate(NI_MAXHOST,cleanup:=true)
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">allocate</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">machine_word</span><span style="color: #0000FF;">(),</span><span style="color: #000000;">cleanup</span><span style="color: #0000FF;">:=</span><span style="color: #004600;">true</span><span style="color: #0000FF;">),</span>
set_struct_field(idAI,hints,"ai_family",AF_UNSPEC)
<span style="color: #000000;">host</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">allocate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">NI_MAXHOST</span><span style="color: #0000FF;">,</span><span style="color: #000000;">cleanup</span><span style="color: #0000FF;">:=</span><span style="color: #004600;">true</span><span style="color: #0000FF;">)</span>
-- set_struct_field(idAI,hints,"ai_socktype",SOCK_STREAM)
<span style="color: #000000;">set_struct_field</span><span style="color: #0000FF;">(</span><span style="color: #000000;">idAI</span><span style="color: #0000FF;">,</span><span style="color: #000000;">hints</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"ai_family"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">AF_UNSPEC</span><span style="color: #0000FF;">)</span>
set_struct_field(idAI,hints,"ai_socktype",SOCK_DGRAM)
<span style="color: #000080;font-style:italic;">-- set_struct_field(idAI,hints,"ai_socktype",SOCK_STREAM)</span>
error = c_func(xgetaddrinfo,{fqdn,NULL,hints,res})
<span style="color: #000000;">set_struct_field</span><span style="color: #0000FF;">(</span><span style="color: #000000;">idAI</span><span style="color: #0000FF;">,</span><span style="color: #000000;">hints</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"ai_socktype"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">SOCK_DGRAM</span><span style="color: #0000FF;">)</span>
if error then ?9/0 end if
<span style="color: #000000;">error</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">c_func</span><span style="color: #0000FF;">(</span><span style="color: #000000;">xgetaddrinfo</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">fqdn</span><span style="color: #0000FF;">,</span><span style="color: #004600;">NULL</span><span style="color: #0000FF;">,</span><span style="color: #000000;">hints</span><span style="color: #0000FF;">,</span><span style="color: #000000;">res</span><span style="color: #0000FF;">})</span>
res = peekNS(res,machine_word(),false)
<span style="color: #008080;">if</span> <span style="color: #000000;">error</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
atom ptr = res
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">peekNS</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">machine_word</span><span style="color: #0000FF;">(),</span><span style="color: #004600;">false</span><span style="color: #0000FF;">)</span>
sequence results = {}
<span style="color: #004080;">atom</span> <span style="color: #000000;">ptr</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">res</span>
while ptr!=NULL do
<span style="color: #004080;">sequence</span> <span style="color: #000000;">results</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
atom addr = get_struct_field(idAI,ptr,"ai_addr")
<span style="color: #008080;">while</span> <span style="color: #000000;">ptr</span><span style="color: #0000FF;">!=</span><span style="color: #004600;">NULL</span> <span style="color: #008080;">do</span>
integer len = get_struct_field(idAI,ptr,"ai_addrlen")
<span style="color: #004080;">atom</span> <span style="color: #000000;">addr</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">get_struct_field</span><span style="color: #0000FF;">(</span><span style="color: #000000;">idAI</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ptr</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"ai_addr"</span><span style="color: #0000FF;">)</span>
error = c_func(xgetnameinfo,{addr, len, host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST})
<span style="color: #004080;">integer</span> <span style="color: #000000;">len</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">get_struct_field</span><span style="color: #0000FF;">(</span><span style="color: #000000;">idAI</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ptr</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"ai_addrlen"</span><span style="color: #0000FF;">)</span>
if error then ?9/0 end if
<span style="color: #000000;">error</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">c_func</span><span style="color: #0000FF;">(</span><span style="color: #000000;">xgetnameinfo</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">addr</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">len</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">host</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">NI_MAXHOST</span><span style="color: #0000FF;">,</span> <span style="color: #004600;">NULL</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">NI_NUMERICHOST</span><span style="color: #0000FF;">})</span>
results = append(results,peek_string(host))
<span style="color: #008080;">if</span> <span style="color: #000000;">error</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
ptr = get_struct_field(idAI,ptr,"ai_next")
<span style="color: #000000;">results</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">results</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">peek_string</span><span style="color: #0000FF;">(</span><span style="color: #000000;">host</span><span style="color: #0000FF;">))</span>
end while
<span style="color: #000000;">ptr</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">get_struct_field</span><span style="color: #0000FF;">(</span><span style="color: #000000;">idAI</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ptr</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"ai_next"</span><span style="color: #0000FF;">)</span>
c_proc(xfreeaddrinfo,{res})
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
return results
<span style="color: #7060A8;">c_proc</span><span style="color: #0000FF;">(</span><span style="color: #000000;">xfreeaddrinfo</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">res</span><span style="color: #0000FF;">})</span>
end function
<span style="color: #008080;">return</span> <span style="color: #000000;">results</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
procedure WSACleanup()
if platform()=WINDOWS then
<span style="color: #008080;">procedure</span> <span style="color: #7060A8;">WSACleanup</span><span style="color: #0000FF;">()</span>
error = c_func(xwsacleanup,{})
<span style="color: #008080;">if</span> <span style="color: #7060A8;">platform</span><span style="color: #0000FF;">()=</span><span style="color: #004600;">WINDOWS</span> <span style="color: #008080;">then</span>
if error then crash("WSACleanup failed: %d\n",{error}) end if
<span style="color: #000000;">error</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">c_func</span><span style="color: #0000FF;">(</span><span style="color: #000000;">xwsacleanup</span><span style="color: #0000FF;">,{})</span>
end if
<span style="color: #008080;">if</span> <span style="color: #000000;">error</span> <span style="color: #008080;">then</span> <span style="color: #7060A8;">crash</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"WSACleanup failed: %d\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">error</span><span style="color: #0000FF;">})</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end procedure
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
 
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
?get_name_info("www.kame.net")
WSACleanup()</lang>
<span style="color: #0000FF;">?</span><span style="color: #000000;">get_name_info</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"www.kame.net"</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">WSACleanup</span><span style="color: #0000FF;">()</span>
<!--</lang>-->
{{out}}
Note that windows nslookup shows an IPv6 that this does not, whereas
7,794

edits