mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Project setup
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -50,3 +50,4 @@ modules.order
|
|||||||
Module.symvers
|
Module.symvers
|
||||||
Mkfile.old
|
Mkfile.old
|
||||||
dkms.conf
|
dkms.conf
|
||||||
|
cmake-build-debug/
|
||||||
@@ -3,4 +3,4 @@ project(c3c C)
|
|||||||
|
|
||||||
set(CMAKE_C_STANDARD 11)
|
set(CMAKE_C_STANDARD 11)
|
||||||
|
|
||||||
add_executable(c3c main.c)
|
add_executable(c3c main.c build/build_options.c build/build_options.h build/project_creation.c build/project_creation.h utils/string_utils.c utils/string_utils.h utils/file_utils.c utils/file_utils.h utils/errors.c utils/errors.h)
|
||||||
7
build/build_options.c
Normal file
7
build/build_options.c
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
// Copyright (c) 2019 Christoffer Lerno. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "build_options.h"
|
||||||
|
|
||||||
|
BuildOptions build_options;
|
||||||
21
build/build_options.h
Normal file
21
build/build_options.h
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// Copyright (c) 2019 Christoffer Lerno. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
#define MAX_LIB_DIRS 1024
|
||||||
|
#define MAX_FILES 2048
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
const char* lib_dir[MAX_LIB_DIRS];
|
||||||
|
int lib_count;
|
||||||
|
const char* files[MAX_FILES];
|
||||||
|
int file_count;
|
||||||
|
const char* project_name;
|
||||||
|
const char* path;
|
||||||
|
const char* original_path;
|
||||||
|
} BuildOptions;
|
||||||
|
|
||||||
|
extern BuildOptions build_options;
|
||||||
129
build/project_creation.c
Normal file
129
build/project_creation.c
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
// Copyright (c) 2019 Christoffer Lerno. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include "project_creation.h"
|
||||||
|
#include "build_options.h"
|
||||||
|
#include "string.h"
|
||||||
|
#include "../utils/string_utils.h"
|
||||||
|
|
||||||
|
const char* TOML =
|
||||||
|
"[[executable]]\n"
|
||||||
|
"# name of the target\n"
|
||||||
|
"name = \"%s\"\n"
|
||||||
|
"# version using semantic versioning\n"
|
||||||
|
"version = \"0.1.0\"\n"
|
||||||
|
"# authors, optionally with email\n"
|
||||||
|
"authors = [\"John Doe <john.doe@example.com>\"]\n"
|
||||||
|
"# language version of C3\n"
|
||||||
|
"langrev = \"1\"\n"
|
||||||
|
"# warnings used\n"
|
||||||
|
"warnings = [\"no-unused\"]\n"
|
||||||
|
"# sources compiled\n"
|
||||||
|
"sources = [\"src/**\"]\n"
|
||||||
|
"# libraries to use\n"
|
||||||
|
"libs = [\"lib/**\"]\n";
|
||||||
|
|
||||||
|
void create_project(void)
|
||||||
|
{
|
||||||
|
for (int i = 0; ; i++)
|
||||||
|
{
|
||||||
|
char c = build_options.project_name[i];
|
||||||
|
if (c == '\0') break;
|
||||||
|
if (!is_alphanum_(c))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "'%s' is not a valid project name.\n", build_options.project_name);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chdir(build_options.path))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Can't open path %s\n", build_options.path);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
int error = mkdir(build_options.project_name, 0755);
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Could not create directory %s: %s\n", build_options.project_name, strerror(errno));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chdir(build_options.project_name)) goto ERROR;
|
||||||
|
|
||||||
|
FILE *file = fopen("LICENCE", "a");
|
||||||
|
if (!file) goto ERROR;
|
||||||
|
fclose(file);
|
||||||
|
|
||||||
|
file = fopen("README.md", "a");
|
||||||
|
if (!file) goto ERROR;
|
||||||
|
fclose(file);
|
||||||
|
|
||||||
|
file = fopen("project.toml", "a");
|
||||||
|
if (!file) goto ERROR;
|
||||||
|
fprintf(file, TOML, build_options.project_name);
|
||||||
|
fclose(file);
|
||||||
|
|
||||||
|
if (mkdir("lib", 0755)) goto ERROR;
|
||||||
|
|
||||||
|
if (mkdir("build", 0755)) goto ERROR;
|
||||||
|
|
||||||
|
if (mkdir("resources", 0755)) goto ERROR;
|
||||||
|
|
||||||
|
if (mkdir("test", 0755)) goto ERROR;
|
||||||
|
|
||||||
|
chdir("test");
|
||||||
|
|
||||||
|
if (mkdir(build_options.project_name, 0755)) goto ERROR;
|
||||||
|
|
||||||
|
chdir("..");
|
||||||
|
|
||||||
|
if (mkdir("docs", 0755)) goto ERROR;
|
||||||
|
|
||||||
|
chdir("docs");
|
||||||
|
|
||||||
|
file = fopen("about.md", "a");
|
||||||
|
if (!file) goto ERROR;
|
||||||
|
fclose(file);
|
||||||
|
|
||||||
|
if (mkdir("src", 0755)) goto ERROR;
|
||||||
|
|
||||||
|
chdir("src");
|
||||||
|
|
||||||
|
file = fopen("index.html", "a");
|
||||||
|
if (!file) goto ERROR;
|
||||||
|
fclose(file);
|
||||||
|
|
||||||
|
chdir("../..");
|
||||||
|
|
||||||
|
if (mkdir("src", 0755)) goto ERROR;
|
||||||
|
|
||||||
|
chdir("src");
|
||||||
|
|
||||||
|
if (mkdir(build_options.project_name, 0755)) goto ERROR;
|
||||||
|
|
||||||
|
chdir(build_options.project_name);
|
||||||
|
|
||||||
|
file = fopen("main.c3", "a");
|
||||||
|
if (!file) goto ERROR;
|
||||||
|
fclose(file);
|
||||||
|
|
||||||
|
chdir("../..");
|
||||||
|
|
||||||
|
printf("Project '%s' created.\n", build_options.project_name);
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
|
||||||
|
ERROR:
|
||||||
|
fprintf(stderr, "Err: %s\n", strerror(errno));
|
||||||
|
|
||||||
|
printf("Something went wrong creating the project.");
|
||||||
|
chdir(build_options.path);
|
||||||
|
rmdir(build_options.project_name);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
8
build/project_creation.h
Normal file
8
build/project_creation.h
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// Copyright (c) 2019 Christoffer Lerno. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
||||||
|
void create_project(void);
|
||||||
181
main.c
181
main.c
@@ -1,6 +1,179 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include "build/build_options.h"
|
||||||
|
#include "build/project_creation.h"
|
||||||
|
#include "utils/errors.h"
|
||||||
|
|
||||||
|
static void usage(const char* name) {
|
||||||
|
fprintf(stderr, "Usage: %s <options> <target>\n", name);
|
||||||
|
fprintf(stderr, "Options:\n");
|
||||||
|
fprintf(stderr, " --lib <dir> - use this directory as the c3 library path\n");
|
||||||
|
fprintf(stderr, " --path <dir> - use this as the base directory for the current command\n");
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
COMMAND_COMPILE,
|
||||||
|
COMMAND_NEW,
|
||||||
|
} CompilerCommand;
|
||||||
|
|
||||||
|
static CompilerCommand command;
|
||||||
|
|
||||||
|
static int arg_index;
|
||||||
|
static int arg_count;
|
||||||
|
static const char** args;
|
||||||
|
static const char* current_arg;
|
||||||
|
|
||||||
|
static void select_compiler_command(CompilerCommand new_command)
|
||||||
|
{
|
||||||
|
if (command != COMMAND_COMPILE)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Please select only one command\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
command = new_command;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* check_dir(const char *path)
|
||||||
|
{
|
||||||
|
if (chdir(path) == -1) error_exit("The path \"%s\" does not point to a valid directory.", path);
|
||||||
|
int err = chdir(build_options.original_path);
|
||||||
|
assert(!err);
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool at_end()
|
||||||
|
{
|
||||||
|
return arg_index == arg_count - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline const char* next_arg()
|
||||||
|
{
|
||||||
|
assert(!at_end());
|
||||||
|
current_arg = args[++arg_index];
|
||||||
|
return current_arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline bool next_is_arg()
|
||||||
|
{
|
||||||
|
return args[arg_index + 1][0] == '-';
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool match_longopt(const char* name)
|
||||||
|
{
|
||||||
|
return strcmp(¤t_arg[2], name) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool match_shortopt(const char* name)
|
||||||
|
{
|
||||||
|
return strcmp(¤t_arg[1], name) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void append_file()
|
||||||
|
{
|
||||||
|
if (build_options.file_count == MAX_FILES)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Max %d files may be specified\n", MAX_FILES);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
build_options.files[build_options.file_count++] = current_arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void parse_option()
|
||||||
|
{
|
||||||
|
switch (current_arg[1])
|
||||||
|
{
|
||||||
|
case 'h':
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
if (match_shortopt("new"))
|
||||||
|
{
|
||||||
|
select_compiler_command(COMMAND_NEW);
|
||||||
|
if (at_end() || next_is_arg()) error_exit("Expected a project name after -new");
|
||||||
|
build_options.project_name = next_arg();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '-':
|
||||||
|
if (match_longopt("about"))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "The C3 Compiler\n");
|
||||||
|
fprintf(stderr, "\nC3 is an evolution of C.\n");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
if (match_longopt("lib"))
|
||||||
|
{
|
||||||
|
if (at_end() || next_is_arg()) error_exit("error: --lib needs a directory.");
|
||||||
|
if (current_arg[0] == '-') error_exit("Expected a directory after --lib.");
|
||||||
|
if (build_options.lib_count == MAX_LIB_DIRS) error_exit("Max %d libraries may be specified.", MAX_LIB_DIRS);
|
||||||
|
build_options.lib_dir[build_options.lib_count++] = check_dir(next_arg());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (match_longopt("path"))
|
||||||
|
{
|
||||||
|
if (at_end() || next_is_arg()) error_exit("error: --path needs a directory.");
|
||||||
|
build_options.path = check_dir(next_arg());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (match_longopt("help"))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
usage(args[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handle_compile_command()
|
||||||
|
{
|
||||||
|
printf("TODO\n");
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void parse_arguments()
|
||||||
|
{
|
||||||
|
command = COMMAND_COMPILE;
|
||||||
|
for (arg_index = 1; arg_index < arg_count; arg_index++)
|
||||||
|
{
|
||||||
|
current_arg = args[arg_index];
|
||||||
|
if (current_arg[0] == '-')
|
||||||
|
{
|
||||||
|
parse_option();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
append_file();
|
||||||
|
}
|
||||||
|
switch (command)
|
||||||
|
{
|
||||||
|
case COMMAND_NEW:
|
||||||
|
create_project();
|
||||||
|
break;
|
||||||
|
case COMMAND_COMPILE:
|
||||||
|
handle_compile_command();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, const char *argv[])
|
||||||
|
{
|
||||||
|
build_options.path = ".";
|
||||||
|
build_options.original_path = getcwd(NULL, 0);
|
||||||
|
arg_count = argc;
|
||||||
|
args = argv;
|
||||||
|
parse_arguments();
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
int main() {
|
|
||||||
printf("Hello, World!\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
5
utils/errors.c
Normal file
5
utils/errors.c
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
// Copyright (c) 2019 Christoffer Lerno. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "errors.h"
|
||||||
7
utils/errors.h
Normal file
7
utils/errors.h
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// Copyright (c) 2019 Christoffer Lerno. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
#define error_exit(...) do { fprintf(stderr, __VA_ARGS__); fprintf(stderr, "\n"); exit(EXIT_FAILURE); } while(0)
|
||||||
20
utils/file_utils.c
Normal file
20
utils/file_utils.c
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
// Copyright (c) 2019 Christoffer Lerno. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "file_utils.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
const char* expand_path(const char* path)
|
||||||
|
{
|
||||||
|
if (path[0] == '~' && path[1] == '/')
|
||||||
|
{
|
||||||
|
// Ignore leak.
|
||||||
|
char *ret = NULL;
|
||||||
|
char *home = getenv("HOME");
|
||||||
|
if (!home || asprintf(&ret, "%s%s", home, &path[1]) == -1) return &path[2];
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
return path;
|
||||||
|
}
|
||||||
8
utils/file_utils.h
Normal file
8
utils/file_utils.h
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// Copyright (c) 2019 Christoffer Lerno. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
||||||
|
const char* expand_path(const char* path);
|
||||||
6
utils/string_utils.c
Normal file
6
utils/string_utils.c
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
// Copyright (c) 2019 Christoffer Lerno. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "string_utils.h"
|
||||||
|
|
||||||
26
utils/string_utils.h
Normal file
26
utils/string_utils.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// Copyright (c) 2019 Christoffer Lerno. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
static inline bool is_lower(char c)
|
||||||
|
{
|
||||||
|
return c >= 'a' && c <= 'z';
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool is_upper(char c)
|
||||||
|
{
|
||||||
|
return c >= 'A' && c <= 'Z';
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool is_alphanum_(char c)
|
||||||
|
{
|
||||||
|
return (c >= 'a' && c <= 'z')
|
||||||
|
|| (c >= 'A' && c <= 'Z')
|
||||||
|
|| (c >= '0' && c <= '9')
|
||||||
|
|| c == '_';
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user