JUSTOCASOU
This commit is contained in:
parent
c358562ecc
commit
a8ca407247
8 changed files with 220 additions and 41 deletions
|
|
@ -7,7 +7,7 @@ DBG_LDFLAGS= -fsanitize=address
|
|||
|
||||
|
||||
SRC_DIR = src
|
||||
LIB_SRCS = lines/lines.c hash_maps/hash_maps.c lists/lists.c
|
||||
LIB_SRCS = lines/lines.c hash_maps/hash_maps.c lists/lists.c files/files.c
|
||||
MAIN_SRCS = main.c minimake.c
|
||||
|
||||
# SRCS = $(patsubst %,$(SRC_DIR)/%, $(MAIN_SRCS))
|
||||
|
|
|
|||
99
minimake/src/files/files.c
Normal file
99
minimake/src/files/files.c
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
#include "files.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
// #include "../lines/lines.h"
|
||||
|
||||
char *get_makefile(struct list *files)
|
||||
{
|
||||
struct list *file = files;
|
||||
int found = 0;
|
||||
|
||||
// Test file presence
|
||||
while (file != NULL && !found)
|
||||
{
|
||||
FILE *test = fopen(file->data, "r");
|
||||
if (test != NULL)
|
||||
{
|
||||
fclose(test);
|
||||
found = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
file = file->next;
|
||||
}
|
||||
}
|
||||
|
||||
char *res = NULL;
|
||||
if (found)
|
||||
res = file->data;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
ssize_t get_file_lastmodiftime(char *filename)
|
||||
{
|
||||
struct stat stat;
|
||||
if (lstat(filename, &stat) == -1)
|
||||
return -1;
|
||||
return stat.st_mtime;
|
||||
}
|
||||
|
||||
// Calls a shell that will run the given command
|
||||
// It will first print the command to run unless the it starts with '@'
|
||||
// Returns the return code o the command or -1 if a syscall fails
|
||||
int run_command(char *command)
|
||||
{
|
||||
if (command[0] == '@')
|
||||
command++;
|
||||
else
|
||||
{
|
||||
puts(command);
|
||||
}
|
||||
|
||||
// Just in case
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
|
||||
// char *executable;
|
||||
// size_t args_offset = readword(command, strlen(command), &executable);
|
||||
|
||||
int id = fork();
|
||||
if (id < 0)
|
||||
{
|
||||
perror("fork");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (id == 0)
|
||||
{
|
||||
int res = 0;
|
||||
wait(&res);
|
||||
// printf("Got return code: %d\n", res);
|
||||
return res;
|
||||
}
|
||||
else
|
||||
{
|
||||
int res = execl("/bin/sh", "(make)", "-c", command, NULL);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns 1 if file exists (and is readable), 0 otherwise
|
||||
int file_exists(char *filename)
|
||||
{
|
||||
if (filename == NULL)
|
||||
return 0;
|
||||
|
||||
FILE *test = fopen(filename, "r");
|
||||
if (test == NULL)
|
||||
return 0;
|
||||
|
||||
fclose(test);
|
||||
return 1;
|
||||
}
|
||||
14
minimake/src/files/files.h
Normal file
14
minimake/src/files/files.h
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
#ifndef FILES_H
|
||||
#define FILES_H
|
||||
|
||||
#define _XOPEN_SOURCE 500
|
||||
|
||||
#include "../lists/lists.h"
|
||||
#include <sys/types.h>
|
||||
|
||||
char* get_makefile(struct list *files);
|
||||
ssize_t get_file_lastmodiftime(char* filename);
|
||||
int run_command(char *command);
|
||||
int file_exists(char *filename);
|
||||
|
||||
#endif // FILES_H
|
||||
|
|
@ -5,6 +5,7 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "files/files.h"
|
||||
#include "lists/lists.h"
|
||||
#include "minimake.h"
|
||||
|
||||
|
|
@ -58,10 +59,12 @@ static int handle_args(int argc, char **argv, struct list **minimake_files,
|
|||
else if (strcmp(argv[i], "-f") == 0)
|
||||
{
|
||||
flags |= FLAGS_CUSTOM_FILE;
|
||||
if (i + 1 == argc || argv[i + 1][0] == '-')
|
||||
i++;
|
||||
|
||||
if (i == argc || argv[i][0] == '-')
|
||||
errx(INVALID_ARG, "No file specified after '-f'");
|
||||
|
||||
files = list_prepend(files, argv[i + 1]);
|
||||
files = list_prepend(files, argv[i]);
|
||||
}
|
||||
// Print
|
||||
else if (strcmp(argv[i], "-p") == 0)
|
||||
|
|
@ -92,33 +95,6 @@ static int handle_args(int argc, char **argv, struct list **minimake_files,
|
|||
return flags;
|
||||
}
|
||||
|
||||
char *get_makefile(struct list *files)
|
||||
{
|
||||
struct list *file = files;
|
||||
int found = 0;
|
||||
|
||||
// Test file presence
|
||||
while (file != NULL && !found)
|
||||
{
|
||||
FILE *test = fopen(file->data, "r");
|
||||
if (test != NULL)
|
||||
{
|
||||
fclose(test);
|
||||
found = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
file = file->next;
|
||||
}
|
||||
}
|
||||
|
||||
char *res = NULL;
|
||||
if (found)
|
||||
res = file->data;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct list *files;
|
||||
|
|
@ -129,8 +105,8 @@ int main(int argc, char **argv)
|
|||
if (filename == NULL)
|
||||
errx(GENERIC_ERR, "No Makefile found");
|
||||
|
||||
make(filename, flags, argv[0]);
|
||||
int res = make(filename, rules, argv[0], flags);
|
||||
list_destroy(files);
|
||||
list_destroy(rules);
|
||||
return 0;
|
||||
return res;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "files/files.h"
|
||||
#include "hash_maps/hash_maps.h"
|
||||
#include "lines/lines.h"
|
||||
#include "lists/lists.h"
|
||||
|
|
@ -459,21 +460,103 @@ void make_parse(char *path)
|
|||
|
||||
// ==== Runtime ====
|
||||
|
||||
// static void make_run(void)
|
||||
// {}
|
||||
// Expands and run a specified rule
|
||||
static int run_rule(struct rule *rule)
|
||||
{
|
||||
struct list *commands = rule->recipe;
|
||||
struct list *dependencies = rule->dependencies;
|
||||
|
||||
// Expand dependencies variables
|
||||
// TODO
|
||||
|
||||
// Build dependencies
|
||||
while (dependencies != NULL)
|
||||
{
|
||||
// Check file existence
|
||||
if (!file_exists(dependencies->data))
|
||||
{
|
||||
// Check rule existence instead
|
||||
struct rule *dep_rule = hashmap_get(rules, dependencies->data);
|
||||
if (dep_rule != NULL)
|
||||
{
|
||||
int res = run_rule(dep_rule);
|
||||
if (res != 0) // Exit on error
|
||||
return res;
|
||||
}
|
||||
else
|
||||
{
|
||||
drop(GENERIC_ERR, "No rule to make target '%s'",
|
||||
dependencies->data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (commands != NULL)
|
||||
{
|
||||
// Expand command variables
|
||||
// TODO
|
||||
|
||||
// Run
|
||||
int res = run_command(commands->data);
|
||||
if (res != 0) // Exit on error
|
||||
return res;
|
||||
|
||||
commands = commands->next;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Run the given rules after parsing
|
||||
int make_run(struct list *given_rules)
|
||||
{
|
||||
if (given_rules == NULL)
|
||||
{
|
||||
// No rule specified => run first rule found in the Makefile
|
||||
if (rules_list == NULL)
|
||||
drop(GENERIC_ERR, "No targets");
|
||||
|
||||
struct rule *full_rule = hashmap_get(rules, rules_list->data);
|
||||
if (full_rule == NULL)
|
||||
drop(GENERIC_ERR,
|
||||
"Internal error: Could not retrieve target '%s' in database",
|
||||
rules_list->data);
|
||||
|
||||
return run_rule(full_rule);
|
||||
}
|
||||
else
|
||||
{
|
||||
while (given_rules != NULL)
|
||||
{
|
||||
struct rule *full_rule = hashmap_get(rules, given_rules->data);
|
||||
if (full_rule == NULL)
|
||||
drop(GENERIC_ERR, "No rule to make target '%s'",
|
||||
given_rules->data);
|
||||
|
||||
int res = run_rule(full_rule);
|
||||
if (res != 0)
|
||||
return res;
|
||||
|
||||
given_rules = given_rules->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// ==== MAKE ====
|
||||
|
||||
void make(char *path, int flags, char *argv0)
|
||||
int make(char *path, struct list *rules, char *exec_name, int flags)
|
||||
{
|
||||
program_name = argv0;
|
||||
program_name = exec_name;
|
||||
|
||||
make_parse(path);
|
||||
|
||||
if (flags & FLAGS_PRINT)
|
||||
dump_database();
|
||||
|
||||
int status = make_run(rules);
|
||||
free_all();
|
||||
return status;
|
||||
}
|
||||
|
||||
// Prints an error message before exiting gracefully (by freeing all variables)
|
||||
|
|
@ -482,9 +565,9 @@ void drop(int status, char *format, ...)
|
|||
// Print
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
fprintf(stderr, "%s: ", program_name);
|
||||
fprintf(stderr, "%s: *** ", program_name);
|
||||
vfprintf(stderr, format, args);
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, ". Stop.\n");
|
||||
va_end(args);
|
||||
|
||||
free_all();
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@
|
|||
#define FLAGS_PRINT 2
|
||||
|
||||
// Default values
|
||||
#define DEFAULT_MAKEFILE "Makefile"
|
||||
#define DEFAULT_MAKEFILE_2 "makefile"
|
||||
#define DEFAULT_MAKEFILE "makefile"
|
||||
#define DEFAULT_MAKEFILE_2 "Makefile"
|
||||
#define BUFFER_SIZE 1024
|
||||
#define HASHMAP_SIZE 32
|
||||
|
||||
|
|
@ -38,8 +38,9 @@ struct rule
|
|||
struct list *recipe;
|
||||
};
|
||||
|
||||
void make(char *path, int flags, char* program_name);
|
||||
int make(char *path, struct list* rules, char *argv0, int flags);
|
||||
void make_parse(char *path);
|
||||
int make_run(struct list *rules);
|
||||
void drop(int status, char *format, ...);
|
||||
void dump_database(void);
|
||||
size_t expand_variable(struct line *line, size_t index, char **value);
|
||||
|
|
|
|||
1
minimake/tests/Makefile.test3
Normal file
1
minimake/tests/Makefile.test3
Normal file
|
|
@ -0,0 +1 @@
|
|||
VAR = 1
|
||||
5
minimake/tests/Makefile.test4
Normal file
5
minimake/tests/Makefile.test4
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
rule1:
|
||||
echo Toto
|
||||
|
||||
rule2:
|
||||
@echo Toto
|
||||
Loading…
Add table
Add a link
Reference in a new issue