Skip to content

Instantly share code, notes, and snippets.

@nrdmn
Last active December 23, 2020 21:37
Show Gist options
  • Save nrdmn/61e87c9084cc6173040a9d144d9107b8 to your computer and use it in GitHub Desktop.
Save nrdmn/61e87c9084cc6173040a9d144d9107b8 to your computer and use it in GitHub Desktop.
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <stdbool.h>
#include <ctype.h>
void unescape(char *buf)
{
char *ptr = buf;
while (*buf != 0) {
if (buf[0] == '\\' && buf[1] != 0) {
buf++;
}
*ptr++ = *buf++;
}
*ptr = 0;
}
bool check_arg(const char *const arg);
bool check_args_file(const char *const filename)
{
struct stat st;
int fd = open(filename, O_RDONLY);
if (fd == 0) {
return false;
}
if (fstat(fd, &st)) {
close(fd);
return false;
}
char *buf = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
close(fd);
if (buf == MAP_FAILED) {
return false;
}
for (size_t i = 0; i < st.st_size; i++) {
if (isspace(buf[i])) {
continue;
}
char *arg = NULL;
size_t len = 0;
if (buf[i] == '"') {
i++;
while (i + len < st.st_size && buf[i + len] != '"') {
if (buf[i + len] == '\\') {
len++;
}
len++;
}
arg = strndup(buf + i, len);
if (arg == NULL) {
exit(EXIT_FAILURE);
}
unescape(arg);
} else if (buf[i] == '\'') {
i++;
while (i + len < st.st_size && buf[i + len] != '\'') {
if (buf[i + len] == '\\') {
len++;
}
len++;
}
arg = strndup(buf + i, len);
if (arg == NULL) {
exit(EXIT_FAILURE);
}
unescape(arg);
} else {
while (i + len < st.st_size && !isspace(buf[i + len])) {
len++;
}
arg = strndup(buf + i, len);
if (arg == NULL) {
exit(EXIT_FAILURE);
}
}
if (check_arg(arg)) {
free(arg);
return true;
}
free(arg);
i += len;
}
return false;
}
bool check_arg(const char *const arg)
{
if (arg[0] == '@' && check_args_file(arg + 1)) {
return true;
}
if (!strcmp(arg, "-E")) {
return true;
}
if (!strcmp(arg, "-Xpreprocessor")) {
return true;
}
return false;
}
int main(int argc, char **argv)
{
for (int i = 1; i < argc; i++) {
if (check_arg(argv[i])) {
if (strlen(argv[0]) >= strlen("clang")) {
strcpy(argv[0], "clang");
}
return execvp("clang", argv);
}
}
if (strlen(argv[0]) >= strlen("lcc")) {
strcpy(argv[0], "lcc");
}
return execvp("lcc", argv);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment