From 77a488376335a1c8fbc02ace150d3940ee7faec8 Mon Sep 17 00:00:00 2001 From: Paul Chaignon Date: Tue, 28 Jun 2016 18:53:35 +0200 Subject: [PATCH] Support the EQ programming language (#3086) --- lib/linguist/languages.yml | 8 + samples/EQ/HTTPServerVirtualHostListener.eq | 235 ++++++++++++++++++ samples/EQ/SEButtonEntity.eq | 181 ++++++++++++++ samples/EQ/String.eq | 251 ++++++++++++++++++++ 4 files changed, 675 insertions(+) create mode 100644 samples/EQ/HTTPServerVirtualHostListener.eq create mode 100644 samples/EQ/SEButtonEntity.eq create mode 100644 samples/EQ/String.eq diff --git a/lib/linguist/languages.yml b/lib/linguist/languages.yml index 3f37aee2..5f0aeccf 100755 --- a/lib/linguist/languages.yml +++ b/lib/linguist/languages.yml @@ -933,6 +933,14 @@ EJS: tm_scope: text.html.js ace_mode: ejs +EQ: + type: programming + color: "#a78649" + extensions: + - .eq + tm_scope: source.cs + ace_mode: csharp + Eagle: type: markup color: "#814C05" diff --git a/samples/EQ/HTTPServerVirtualHostListener.eq b/samples/EQ/HTTPServerVirtualHostListener.eq new file mode 100644 index 00000000..d16e23dc --- /dev/null +++ b/samples/EQ/HTTPServerVirtualHostListener.eq @@ -0,0 +1,235 @@ + +/* + * This file is part of Jkop + * Copyright (c) 2016 Job and Esther Technologies, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +IFNDEF("target_posix") +{ + public class HTTPServerVirtualHostListener : EventLoopReadListener + { + public static HTTPServerVirtualHostListener create(String name, HTTPServer server, String prefix = null) { + Logger logger; + if(server != null) { + logger = server.get_logger(); + } + Log.error("Virtual hosts are not supported on this platform.", logger); + return(null); + } + + public void on_read_ready() { + } + + public void close() { + } + } +} + +ELSE { + +public class HTTPServerVirtualHostListener : LoggerObject, EventLoopReadListener +{ + class Client : LoggerObject, EventLoopReadListener + { + HTTPServer server; + LocalSocket socket; + EventLoopEntry ee; + + embed "c" {{{ + #include + #include + #include + }}} + + public static Client create(HTTPServer server, LocalSocket socket) { + if(server == null || socket == null) { + return(null); + } + var eventloop = server.get_eventloop(); + if(eventloop == null) { + return(null); + } + var v = new Client(); + v.set_logger(server.get_logger()); + v.server = server; + v.socket = socket; + v.ee = eventloop.entry_for_object(socket); + if(v.ee == null) { + return(null); + } + v.ee.set_read_listener(v); + return(v); + } + + public void close() { + if(ee != null) { + ee.remove(); + ee = null; + } + if(socket != null) { + socket.close(); + socket = null; + } + server = null; + } + + public void on_read_ready() { + receive_fd(); + close(); + } + + private void receive_fd() { + if(socket is FileDescriptor == false) { + return; + } + int lsfd = ((FileDescriptor)socket).get_fd(); + int r; + int newfd = -1; + embed "c" {{{ + char buf[64]; + struct msghdr msg; + struct iovec iov[1]; + ssize_t n; + union { + struct cmsghdr cm; + char control[CMSG_SPACE(sizeof(int))]; + } control_un; + struct cmsghdr* cmptr; + msg.msg_control = control_un.control; + msg.msg_controllen = sizeof(control_un.control); + msg.msg_name = NULL; + msg.msg_namelen = 0; + iov[0].iov_base = buf; + iov[0].iov_len = 64; + msg.msg_iov = iov; + msg.msg_iovlen = 1; + r = recvmsg(lsfd, &msg, 0); + }}} + if(r < 0) { + log_error("FAILED to recvmsg() from the local socket in virtual host receiver."); + return; + } + embed "c" {{{ + if((cmptr = CMSG_FIRSTHDR(&msg)) != NULL && cmptr->cmsg_len == CMSG_LEN(sizeof(int))) { + if(cmptr->cmsg_level == SOL_SOCKET && cmptr->cmsg_type == SCM_RIGHTS) { + newfd = *((int*)CMSG_DATA(cmptr)); + } + } + }}} + if(newfd < 0) { + log_warning("No file descriptor was passed through the socket in virtual host receiver."); + return; + } + var newsock = TCPSocket.create(); + if(newsock == null) { + embed "c" {{{ close(newfd); }}} + log_error("FAILED to create a new socket"); + return; + } + var fds = newsock as FileDescriptorSocket; + if(fds == null) { + embed "c" {{{ close(newfd); }}} + log_error("TCPSocket is not a FileDescriptorSocket. Cannot set file descriptor."); + return; + } + fds.set_fd(newfd); + server.on_new_client_socket(newsock); + } + } + + HTTPServer server; + LocalSocket socket; + EventLoopEntry ee; + String socketprefix; + + public static HTTPServerVirtualHostListener create(String name, HTTPServer server, String prefix = null) { + if(server == null) { + return(null); + } + var v = new HTTPServerVirtualHostListener(); + v.server = server; + v.socketprefix = prefix; + v.set_logger(server.get_logger()); + if(v.start(name) == false) { + v = null; + } + return(v); + } + + public bool start(String name) { + if(String.is_empty(name) || server == null) { + return(false); + } + socket = LocalSocket.create(); + if(socket == null) { + log_error("Cannot create local socket"); + return(false); + } + var pp = socketprefix; + if(String.is_empty(pp)) { + pp = "sympathy_vhost_"; + } + var socketname = "%s%s".printf().add(pp).add(name).to_string(); + if(socket != null) { + if(socket.listen(socketname) == false) { + socket = null; + } + } + if(socket == null) { + log_error("FAILED to listen to local socket `%s'".printf().add(socketname)); + return(false); + } + var event_loop = server.get_eventloop(); + if(event_loop == null) { + log_error("No eventloop"); + return(false); + } + ee = event_loop.entry_for_object(socket); + if(ee == null) { + log_error("Failed to register socket with eventloop"); + return(false); + } + ee.set_read_listener(this); + log_debug("HTTPServerVirtualHostListener: Listening for virtual host `%s'".printf().add(name)); + return(true); + } + + public void close() { + if(ee != null) { + ee.remove(); + ee = null; + } + if(socket != null) { + socket.close(); + socket = null; + } + server = null; + } + + public void on_read_ready() { + var ns = socket.accept(); + if(ns != null) { + Client.create(server, ns); + } + } +} + +} diff --git a/samples/EQ/SEButtonEntity.eq b/samples/EQ/SEButtonEntity.eq new file mode 100644 index 00000000..9f22f1e3 --- /dev/null +++ b/samples/EQ/SEButtonEntity.eq @@ -0,0 +1,181 @@ + +/* + * This file is part of Jkop + * Copyright (c) 2016 Job and Esther Technologies, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +public class SEButtonEntity : SESpriteEntity, SEPointerListener +{ + class SEImageButtonEntity : SEButtonEntity + { + property SEImage image_normal; + property SEImage image_hover; + property SEImage image_pressed; + + public void update() { + if(get_pressed()) { + var img = image_pressed; + if(img == null) { + img = image_hover; + } + if(img == null) { + img = image_normal; + } + set_image(img); + } + else if(get_has_pointer()) { + var img = image_hover; + if(img == null) { + img = image_normal; + } + set_image(img); + } + else { + set_image(image_normal); + } + } + } + + class SETextButtonEntity : SEButtonEntity + { + property String button_text; + property String normal_font; + property String hover_font; + property String pressed_font; + + public void update() { + if(get_pressed()) { + var ff = pressed_font; + if(String.is_empty(ff)) { + ff = hover_font; + } + if(String.is_empty(ff)) { + ff = normal_font; + } + set_text(button_text, ff); + } + else if(get_has_pointer()) { + var ff = hover_font; + if(String.is_empty(ff)) { + ff = normal_font; + } + set_text(button_text, ff); + } + else { + set_text(button_text, normal_font); + } + } + } + + public static SEButtonEntity for_image(SEImage img) { + return(SEButtonEntity.for_images(img, null, null)); + } + + public static SEButtonEntity for_images(SEImage normal, SEImage hover, SEImage pressed) { + return(new SEImageButtonEntity().set_image_normal(normal).set_image_hover(hover) + .set_image_pressed(pressed)); + } + + public static SEButtonEntity for_text(String text, String normal_font = null, String hover_font = null, String pressed_font = null) { + return(new SETextButtonEntity().set_button_text(text).set_normal_font(normal_font).set_hover_font(hover_font) + .set_pressed_font(pressed_font)); + } + + property SEMessageListener listener; + property Object data; + bool pressed = false; + bool has_pointer = false; + + public bool get_pressed() { + return(pressed); + } + + public bool get_has_pointer() { + return(has_pointer); + } + + public void initialize(SEResourceCache rsc) { + base.initialize(rsc); + update(); + } + + public virtual void update() { + } + + public virtual void on_pointer_enter(SEPointerInfo pi) { + if(has_pointer) { + return; + } + has_pointer = true; + update(); + } + + public virtual void on_pointer_leave(SEPointerInfo pi) { + if(has_pointer == false && pressed == false) { + return; + } + has_pointer = false; + pressed = false; + update(); + } + + public void on_pointer_move(SEPointerInfo pi) { + if(pi.is_inside(get_x(), get_y(), get_width(), get_height())) { + if(has_pointer == false) { + on_pointer_enter(pi); + } + } + else { + if(has_pointer) { + on_pointer_leave(pi); + } + } + } + + public void on_pointer_press(SEPointerInfo pi) { + if(pressed) { + return; + } + if(pi.is_inside(get_x(), get_y(), get_width(), get_height()) == false) { + return; + } + pressed = true; + update(); + } + + public void on_pointer_release(SEPointerInfo pi) { + if(pressed == false) { + return; + } + if(pi.is_inside(get_x(), get_y(), get_width(), get_height()) == false) { + return; + } + on_pointer_click(pi); + pressed = false; + update(); + } + + public virtual void on_pointer_click(SEPointerInfo pi) { + if(listener != null) { + listener.on_message(data); + } + } +} diff --git a/samples/EQ/String.eq b/samples/EQ/String.eq new file mode 100644 index 00000000..73d0ee8f --- /dev/null +++ b/samples/EQ/String.eq @@ -0,0 +1,251 @@ + +/* + * This file is part of Jkop + * Copyright (c) 2016 Job and Esther Technologies, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +public interface String : Stringable, Integer, Double, Boolean +{ + public static String instance(String o) { + if(o == null) { + return(""); + } + return(o); + } + + public static String as_string(Object o) { + if(o == null) { + return(null); + } + if(o is String) { + return((String)o); + } + if(o is Stringable) { + return(((Stringable)o).to_string()); + } + return(null); + } + + public static strptr as_strptr(Object o) { + var str = as_string(o); + if(str == null) { + return(null); + } + return(str.to_strptr()); + } + + public static bool is_in_collection(String str, Collection c) { + if(str == null) { + return(false); + } + foreach(String s in c) { + if(s.equals(str)) { + return(true); + } + } + return(false); + } + + public static bool is_empty(Object o) { + if(o == null) { + return(true); + } + var str = o as String; + if(str == null && o is Stringable) { + str = ((Stringable)o).to_string(); + } + if(str == null) { + return(true); + } + if(str.get_char(0) < 1) { + return(true); + } + return(false); + } + + public static String for_object(Object o) { + if(o is String) { + return((String)o); + } + if(o is Stringable) { + return(((Stringable)o).to_string()); + } + return(null); + } + + public static String for_character(int c) { + var sb = StringBuffer.create(); + sb.append_c(c); + return(sb.to_string()); + } + + public static String for_integer(int av) { + IFDEF("target_cs") { + strptr v; + embed {{{ + v = av.ToString(); + }}} + return(String.for_strptr(v)); + } + ELSE IFDEF("target_java") { + strptr st; + embed {{{ + st = java.lang.String.valueOf(av); + }}} + return(String.for_strptr(st)); + } + ELSE { + return("%d".printf().add(av).to_string()); + } + } + + public static String for_long(long av) { + IFDEF("target_cs") { + strptr v; + embed {{{ + v = av.ToString(); + }}} + return(String.for_strptr(v)); + } + ELSE IFDEF("target_java") { + strptr st; + embed {{{ + st = java.lang.String.valueOf(av); + }}} + return(String.for_strptr(st)); + } + ELSE { + return(for_integer((int)av)); + } + } + + public static String for_double(double v) { + IFDEF("target_java") { + strptr st; + embed {{{ + st = java.lang.String.valueOf(v); + }}} + return(String.for_strptr(st)); + } + ELSE { + return("%f".printf().add(v).to_string()); + } + } + + public static String for_boolean(bool val) { + if(val) { + return("true"); + } + return("false"); + } + + public static String for_strptr(strptr literal) { + var v = new StringImpl(); + v.set_strptr(literal); + return(v); + } + + public static String for_utf8_buffer(Buffer data, bool haszero = true) { + var v = new StringImpl(); + v.set_utf8_buffer(data, haszero); + return(v); + } + + public static String combine(Collection strings, int delim = -1, bool unique = false) { + var sb = StringBuffer.create(); + HashTable flags; + if(unique) { + flags = HashTable.create(); + } + foreach(Object o in strings) { + var s = String.as_string(o); + if(s == null) { + continue; + } + if(flags != null) { + if(flags.get(s) != null) { + continue; + } + flags.set(s, "true"); + } + if(delim > 0 && sb.count() > 0) { + sb.append_c(delim); + } + sb.append(s); + } + return(sb.to_string()); + } + + public static String capitalize(String str) { + if(str == null) { + return(null); + } + var c0 = str.get_char(0); + if(c0 < 1) { + return(null); + } + if(c0 >= 'a' && c0 <= 'z') { + var sb = StringBuffer.create(); + sb.append_c(c0 - 'a' + 'A'); + sb.append(str.substring(1)); + return(sb.to_string()); + } + return(str); + } + + public StringFormatter printf(); + public String dup(); + public String append(String str); + public int get_length(); + public int get_char(int n); + public String truncate(int len); + public String replace(int o, int r); + public String replace_char(int o, int r); + public String replace_string(String o, String r); + public String remove(int start, int len); + public String insert(String str, int pos); + public String substring(int start, int alength = -1); + public String reverse(); + public String lowercase(); + public String uppercase(); + public String strip(); + public Iterator split(int delim, int max = -1); + public int str(String s); + public bool contains(String s); + public int rstr(String s); + public int chr(int c); + public int rchr(int c); + public bool has_prefix(String prefix); + public bool has_suffix(String suffix); + public int compare(Object ao); + public int compare_ignore_case(Object ao); + public bool equals(Object ao); + public bool equals_ptr(strptr str); + public bool equals_ignore_case(Object ao); + public bool equals_ignore_case_ptr(strptr str); + public StringIterator iterate(); + public StringIterator iterate_reverse(); + public int to_integer_base(int ibase); + public strptr to_strptr(); + public Buffer to_utf8_buffer(bool zero = true); + public int hash(); + public EditableString as_editable(); +} \ No newline at end of file