Skip to content

Instantly share code, notes, and snippets.

@tadd
Created January 4, 2010 15:46
Show Gist options
  • Select an option

  • Save tadd/268602 to your computer and use it in GitHub Desktop.

Select an option

Save tadd/268602 to your computer and use it in GitHub Desktop.
ffsc - far faster Scala compiler
/*
* ffsc - far faster scala compiler, omit booting time of fsc(1)
*
* Copyright (c) 2010 Tadashi Saito
*
* 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.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <glib.h>
#include <gio/gio.h>
gboolean open_socket(GSocketClient **client, GSocketConnectable **address,
GSocketConnection **connection);
int run_fsc(int argc, char *argv[]);
void send_command(GIOStream *stream, int argc, char *argv[]);
void print_response(GIOStream *stream);
enum { BUF_SIZE = 1024 };
int main(int argc, char *argv[])
{
GSocketClient *client;
GSocketConnectable *address;
GSocketConnection *connection;
g_type_init();
g_set_prgname("ffsc");
if (!open_socket(&client, &address, &connection))
return run_fsc(argc, argv);
send_command(G_IO_STREAM(connection), argc, argv);
print_response(G_IO_STREAM(connection));
g_object_unref(connection);
g_object_unref(address);
g_object_unref(client);
return 0;
}
gboolean find_port_and_password(guint16 *port, GString **password);
gboolean open_socket(GSocketClient **client, GSocketConnectable **address,
GSocketConnection **connection)
{
GOutputStream *out;
guint16 port;
GString *password;
if (!find_port_and_password(&port, &password))
return FALSE;
*client = g_socket_client_new();
*address = g_network_address_new("localhost", port);
*connection = g_socket_client_connect(*client, *address, NULL, NULL);
out = g_io_stream_get_output_stream(G_IO_STREAM(*connection));
g_output_stream_write_all(out, password->str, password->len, NULL, NULL, NULL);
g_output_stream_write_all(out, "\n", 1, NULL, NULL, NULL);
g_string_free(password, TRUE);
return TRUE;
}
GString *find_port_dir_path(void);
char *chop(char *buf);
gboolean find_port_and_password(guint16 *port, GString **password)
{
GString *dirpath;
GFile *dir;
GFileEnumerator *enumerator;
GFileInfo *info = NULL;
gboolean file_exists = FALSE;
dirpath = find_port_dir_path();
dir = g_file_new_for_path(dirpath->str);
enumerator = g_file_enumerate_children(dir, "standard::name", 0, NULL, NULL);
while ((info = g_file_enumerator_next_file(enumerator, NULL, NULL)) != NULL) {
const gchar *const filename = g_file_info_get_name(info);
if (g_regex_match_simple("^\\d+$", filename, 0, 0)) {
GString *path = g_string_new(NULL);
GFile *portfile;
GFileInputStream *in;
gchar buf[BUF_SIZE];
*port = (guint16) strtol(filename, NULL, 10);
g_string_printf(path, "%s/%s", dirpath->str, filename);
portfile = g_file_new_for_path(path->str);
in = g_file_read(portfile, NULL, NULL);
g_input_stream_read_all(G_INPUT_STREAM(in), buf, sizeof(buf), NULL, NULL, NULL);
*password = g_string_new(chop(buf));
g_object_unref(in);
g_object_unref(portfile);
g_string_free(path, TRUE);
g_object_unref(info);
file_exists = TRUE;
break;
}
g_object_unref(info);
}
g_object_unref(enumerator);
g_object_unref(dir);
g_string_free(dirpath, TRUE);
return file_exists;
}
GString *find_port_dir_path(void)
{
#ifndef WIN32
GString *path = g_string_new(NULL);
g_string_printf(path, "/tmp/scala-devel/%s/scalac-compile-server-port/",
g_get_user_name());
return path;
#else
#endif
}
char *chop(char *buf)
{
size_t end = strlen(buf) - 1;
buf[end-2] = buf[end-1] = buf[end] = '\0';
return buf;
}
GString *join(int len, char *list[], int glue);
int run_fsc(int argc, char *argv[])
{
int retval;
GString *joined, *command = g_string_new("fsc ");
joined = join(argc-1, argv+1, ' ');
g_string_append(command, joined->str);
g_string_free(joined, TRUE);
retval = system(command->str);
g_string_free(command, TRUE);
return retval;
}
GString *join(int size, char *list[], int glue)
{
int i;
GString *str = g_string_new(NULL);
for (i = 0; i < size-1; i++) {
g_string_append(str, list[i]);
g_string_append_c(str, glue);
}
g_string_append(str, list[size-1]);
return str;
}
void send_command(GIOStream *socket, int argc, char *argv[])
{
GString *encoded;
GOutputStream *out = g_io_stream_get_output_stream(socket);
encoded = join(argc-1, argv+1, '\0');
g_output_stream_write_all(out, encoded->str, encoded->len, NULL, NULL, NULL);
g_output_stream_write_all(out, "\n", 1, NULL, NULL, NULL);
g_string_free(encoded, TRUE);
}
void print_response(GIOStream *socket)
{
gchar buf[1024];
GInputStream *in = g_io_stream_get_input_stream(socket);
g_input_stream_read_all(in, buf, sizeof(buf), NULL, NULL, NULL);
printf("%s", buf);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment