167 lines
3.1 KiB
C
167 lines
3.1 KiB
C
/* This file is part of the software similarity tester SIM.
|
|
Written by Dick Grune, Vrije Universiteit, Amsterdam.
|
|
$Id: newargs.c,v 2.11 2016-05-13 19:00:52 dick Exp $
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "sim.h"
|
|
#include "ForEachFile.h"
|
|
#include "Malloc.h"
|
|
#include "newargs.h"
|
|
|
|
#define ARGS_INCR 1024
|
|
static char *args;
|
|
static size_t args_free;
|
|
static size_t args_size;
|
|
|
|
static void
|
|
init_args(void) {
|
|
args = 0;
|
|
args_free = 0;
|
|
args_size = 0;
|
|
}
|
|
|
|
static void
|
|
add_char_to_args(char ch) {
|
|
if (args_free == args_size) {
|
|
/* allocated array is full; increase its size */
|
|
size_t new_size = args_size + ARGS_INCR;
|
|
char *new_args = (char *)Realloc(
|
|
(char *)args, sizeof (char *) * new_size
|
|
);
|
|
args = new_args, args_size = new_size;
|
|
}
|
|
|
|
/* now we are sure there is room enough */
|
|
args[args_free++] = ch;
|
|
}
|
|
|
|
static void
|
|
add_string_to_args(const Fchar *fn) {
|
|
while (*fn) {
|
|
add_char_to_args(*fn++);
|
|
}
|
|
add_char_to_args('\n');
|
|
}
|
|
|
|
static char *
|
|
std_input(void) {
|
|
/* in the form (name \n)* \0 */
|
|
|
|
/* get all of standard input */
|
|
int ch;
|
|
int last_char = '\n';
|
|
|
|
while (ch = getchar(), ch != EOF) {
|
|
/* omit duplicate layout (= empty name) */
|
|
if (last_char == '\n' && ch == '\n') continue;
|
|
|
|
add_char_to_args((char)ch);
|
|
last_char = ch;
|
|
}
|
|
add_char_to_args('\0');
|
|
|
|
/* make sure the result conforms to the form above */
|
|
if (args[args_free-2] != '\n')
|
|
fatal("standard input not terminated with newline");
|
|
|
|
return args;
|
|
}
|
|
|
|
static int
|
|
n_names(const char *s) {
|
|
int cnt = 0;
|
|
|
|
while (*s) {
|
|
if (*s == '\n') {
|
|
cnt++;
|
|
}
|
|
s++;
|
|
}
|
|
return cnt;
|
|
}
|
|
|
|
static const char **
|
|
new_argv(int argc, char *args) {
|
|
/* converts the layout in args to \0, and constructs an argv list */
|
|
const char **argv =
|
|
(const char **)Malloc((size_t)(argc+1) * sizeof (char *));
|
|
char *p = args;
|
|
char last_char = '\n';
|
|
|
|
argc = 0;
|
|
while (*p) {
|
|
if (last_char == '\n') {
|
|
/* here a new name starts */
|
|
argv[argc++] = p;
|
|
}
|
|
last_char = *p;
|
|
if (*p == '\n') {
|
|
*p = '\0';
|
|
}
|
|
p++;
|
|
}
|
|
argv[argc] = 0;
|
|
|
|
return argv;
|
|
}
|
|
|
|
void
|
|
get_new_std_input_args(int *argcp, const char **argvp[]) {
|
|
init_args();
|
|
char *n_args = std_input();
|
|
int argc = n_names(n_args);
|
|
const char **argv = new_argv(argc, n_args);
|
|
|
|
*argcp = argc, *argvp = argv;
|
|
}
|
|
|
|
static int
|
|
register_file(const Fchar *fn, const char *msg, const struct stat *fs) {
|
|
if (msg) {
|
|
fprintf(stderr, "could not handle file %s: %s\n", fn, msg);
|
|
return 0;
|
|
}
|
|
|
|
if ( /* it is a non-empty regular file */
|
|
S_ISREG(fs->st_mode) && fs->st_size > 0
|
|
) {
|
|
add_string_to_args(fn);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
static char *
|
|
recursive_args(int argc, const char *argv[]) {
|
|
if (argc == 0) {
|
|
ForEachFile(str2Fname("."), register_file);
|
|
}
|
|
else {
|
|
int i;
|
|
|
|
for (i = 0; i < argc; i++) {
|
|
const char *arg = argv[i];
|
|
const Fchar *Farg = str2Fname(arg);
|
|
if (is_new_old_separator(arg)) {
|
|
add_string_to_args(Farg);
|
|
} else {
|
|
ForEachFile(Farg, register_file);
|
|
}
|
|
}
|
|
}
|
|
add_char_to_args('\0');
|
|
|
|
return args;
|
|
}
|
|
|
|
void
|
|
get_new_recursive_args(int *argcp, const char **argvp[]) {
|
|
init_args();
|
|
char *n_args = recursive_args(*argcp, *argvp);
|
|
int argc = n_names(n_args);
|
|
const char **argv = new_argv(argc, n_args);
|
|
|
|
*argcp = argc, *argvp = argv;
|
|
}
|