Annotation For xvfs-create-c.c

Origin for each line in xvfs-create-c.c from check-in 160dcdcda4:

eebfe1f40f 2020-03-25        rkeene: #include <sys/stat.h>
eebfe1f40f 2020-03-25        rkeene: #include <stdlib.h>
eebfe1f40f 2020-03-25        rkeene: #include <string.h>
eebfe1f40f 2020-03-25        rkeene: #include <dirent.h>
eebfe1f40f 2020-03-25        rkeene: #include <stdio.h>
eebfe1f40f 2020-03-25        rkeene: #include <ctype.h>
eebfe1f40f 2020-03-25        rkeene: #include <fcntl.h>
eebfe1f40f 2020-03-25        rkeene: 
160dcdcda4 2020-04-03        rkeene: struct xvfs_options {
eebfe1f40f 2020-03-25        rkeene: 	char *name;
eebfe1f40f 2020-03-25        rkeene: 	char *directory;
eebfe1f40f 2020-03-25        rkeene: };
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: struct xvfs_state {
eebfe1f40f 2020-03-25        rkeene: 	char **children;
eebfe1f40f 2020-03-25        rkeene: 	unsigned long child_count;
eebfe1f40f 2020-03-25        rkeene: 	unsigned long child_len;
eebfe1f40f 2020-03-25        rkeene: 	int bucket_count;
eebfe1f40f 2020-03-25        rkeene: 	int max_index;
eebfe1f40f 2020-03-25        rkeene: };
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: enum xvfs_minirivet_mode {
eebfe1f40f 2020-03-25        rkeene: 	XVFS_MINIRIVET_MODE_COPY,
eebfe1f40f 2020-03-25        rkeene: 	XVFS_MINIRIVET_MODE_TCL,
eebfe1f40f 2020-03-25        rkeene: 	XVFS_MINIRIVET_MODE_TCL_PRINT
eebfe1f40f 2020-03-25        rkeene: };
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: /*
eebfe1f40f 2020-03-25        rkeene:  * adler32() function from zlib 1.1.4 and under the same license
eebfe1f40f 2020-03-25        rkeene:  */
eebfe1f40f 2020-03-25        rkeene: static unsigned long adler32(unsigned long adler, const unsigned char *buf, unsigned int len) {
eebfe1f40f 2020-03-25        rkeene: 	const int len_max = 5552;
eebfe1f40f 2020-03-25        rkeene: 	const unsigned long base = 65521;
eebfe1f40f 2020-03-25        rkeene: 	unsigned long s1 = adler & 0xffff;
eebfe1f40f 2020-03-25        rkeene: 	unsigned long s2 = (adler >> 16) & 0xffff;
eebfe1f40f 2020-03-25        rkeene: 	int k, i;
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 	if (buf == NULL) {
eebfe1f40f 2020-03-25        rkeene: 		return(1UL);
eebfe1f40f 2020-03-25        rkeene: 	}
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 	while (len > 0) {
eebfe1f40f 2020-03-25        rkeene: 		k = len < len_max ? len : len_max;
eebfe1f40f 2020-03-25        rkeene: 		len -= k;
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 		while (k >= 16) {
eebfe1f40f 2020-03-25        rkeene: 			for (i = 0; i < 16; i++) {
eebfe1f40f 2020-03-25        rkeene: 				s2 += buf[i];
eebfe1f40f 2020-03-25        rkeene: 			}
eebfe1f40f 2020-03-25        rkeene: 			s1 = buf[15];
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 			buf += 16;
eebfe1f40f 2020-03-25        rkeene: 			k   -= 16;
eebfe1f40f 2020-03-25        rkeene: 		}
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 		if (k != 0) {
eebfe1f40f 2020-03-25        rkeene: 			do {
eebfe1f40f 2020-03-25        rkeene: 				s1 += *buf++;
eebfe1f40f 2020-03-25        rkeene: 				s2 += s1;
eebfe1f40f 2020-03-25        rkeene: 			} while (--k);
eebfe1f40f 2020-03-25        rkeene: 		}
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 		s1 %= base;
eebfe1f40f 2020-03-25        rkeene: 		s2 %= base;
eebfe1f40f 2020-03-25        rkeene: 	}
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 	return((s2 << 16) | s1);
eebfe1f40f 2020-03-25        rkeene: }
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: /*
eebfe1f40f 2020-03-25        rkeene:  * Handle XVFS Rivet template file substitution
eebfe1f40f 2020-03-25        rkeene:  */
eebfe1f40f 2020-03-25        rkeene: static void parse_xvfs_minirivet_file(FILE *outfp, const char * const external_file_name, const char * const internal_file_name) {
eebfe1f40f 2020-03-25        rkeene: 	FILE *fp;
eebfe1f40f 2020-03-25        rkeene: 	unsigned long file_size;
eebfe1f40f 2020-03-25        rkeene: 	unsigned char buf[10];
eebfe1f40f 2020-03-25        rkeene: 	size_t item_count;
eebfe1f40f 2020-03-25        rkeene: 	int idx;
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 	fp = fopen(external_file_name, "rb");
eebfe1f40f 2020-03-25        rkeene: 	if (!fp) {
eebfe1f40f 2020-03-25        rkeene: 		return;
eebfe1f40f 2020-03-25        rkeene: 	}
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 	fprintf(outfp, "\t{\n");
eebfe1f40f 2020-03-25        rkeene: 	fprintf(outfp, "\t\t.name = \"%s\",\n", internal_file_name);
eebfe1f40f 2020-03-25        rkeene: 	fprintf(outfp, "\t\t.type = XVFS_FILE_TYPE_REG,\n");
eebfe1f40f 2020-03-25        rkeene: 	fprintf(outfp, "\t\t.data.fileContents = (const unsigned char *) \"");
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 	file_size = 0;
eebfe1f40f 2020-03-25        rkeene: 	while (1) {
eebfe1f40f 2020-03-25        rkeene: 		item_count = fread(&buf, 1, sizeof(buf), fp);
eebfe1f40f 2020-03-25        rkeene: 		if (item_count <= 0) {
eebfe1f40f 2020-03-25        rkeene: 			break;
eebfe1f40f 2020-03-25        rkeene: 		}
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 		if (file_size != 0) {
eebfe1f40f 2020-03-25        rkeene: 			fprintf(outfp, "\n\t\t\t\"");
eebfe1f40f 2020-03-25        rkeene: 		}
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 		for (idx = 0; idx < item_count; idx++) {
eebfe1f40f 2020-03-25        rkeene: 			fprintf(outfp, "\\x%02x", (int) buf[idx]);
eebfe1f40f 2020-03-25        rkeene: 		}
eebfe1f40f 2020-03-25        rkeene: 		fprintf(outfp, "\"");
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 		file_size += item_count;
eebfe1f40f 2020-03-25        rkeene: 	}
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 	fclose(fp);
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 	fprintf(outfp, ",\n");
eebfe1f40f 2020-03-25        rkeene: 	fprintf(outfp, "\t\t.size = %lu\n", file_size);
eebfe1f40f 2020-03-25        rkeene: 	fprintf(outfp, "\t},\n");
eebfe1f40f 2020-03-25        rkeene: }
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: static void parse_xvfs_minirivet_directory(FILE *outfp, struct xvfs_state *xvfs_state, const char * const directory, const char * const prefix) {
eebfe1f40f 2020-03-25        rkeene: 	const unsigned int max_path_len = 8192, max_children = 65536;
eebfe1f40f 2020-03-25        rkeene: 	unsigned long child_idx, child_count;
eebfe1f40f 2020-03-25        rkeene: 	DIR *dp;
eebfe1f40f 2020-03-25        rkeene: 	struct dirent *file_info;
eebfe1f40f 2020-03-25        rkeene: 	struct stat file_stat;
eebfe1f40f 2020-03-25        rkeene: 	char *full_path_buf;
eebfe1f40f 2020-03-25        rkeene: 	char *rel_path_buf;
eebfe1f40f 2020-03-25        rkeene: 	char **children;
eebfe1f40f 2020-03-25        rkeene: 	int stat_ret;
eebfe1f40f 2020-03-25        rkeene: 	int snprintf_ret;
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 	dp = opendir(directory);
eebfe1f40f 2020-03-25        rkeene: 	if (!dp) {
eebfe1f40f 2020-03-25        rkeene: 		return;
eebfe1f40f 2020-03-25        rkeene: 	}
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 	full_path_buf = malloc(max_path_len);
eebfe1f40f 2020-03-25        rkeene: 	rel_path_buf = malloc(max_path_len);
eebfe1f40f 2020-03-25        rkeene: 	children = malloc(sizeof(*children) * max_children);
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 	child_idx = 0;
eebfe1f40f 2020-03-25        rkeene: 	while (1) {
eebfe1f40f 2020-03-25        rkeene: 		file_info = readdir(dp);
eebfe1f40f 2020-03-25        rkeene: 		if (!file_info) {
eebfe1f40f 2020-03-25        rkeene: 			break;
eebfe1f40f 2020-03-25        rkeene: 		}
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 		if (strcmp(file_info->d_name, ".") == 0) {
eebfe1f40f 2020-03-25        rkeene: 			continue;
eebfe1f40f 2020-03-25        rkeene: 		}
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 		if (strcmp(file_info->d_name, "..") == 0) {
eebfe1f40f 2020-03-25        rkeene: 			continue;
eebfe1f40f 2020-03-25        rkeene: 		}
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 		snprintf_ret = snprintf(full_path_buf, max_path_len, "%s/%s", directory, file_info->d_name);
eebfe1f40f 2020-03-25        rkeene: 		if (snprintf_ret >= max_path_len) {
eebfe1f40f 2020-03-25        rkeene: 			continue;
eebfe1f40f 2020-03-25        rkeene: 		}
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 		snprintf_ret = snprintf(rel_path_buf, max_path_len, "%s%s%s",
eebfe1f40f 2020-03-25        rkeene: 			prefix,
eebfe1f40f 2020-03-25        rkeene: 			strcmp(prefix, "") == 0 ? "" : "/",
eebfe1f40f 2020-03-25        rkeene: 			file_info->d_name
eebfe1f40f 2020-03-25        rkeene: 		);
eebfe1f40f 2020-03-25        rkeene: 		if (snprintf_ret >= max_path_len) {
eebfe1f40f 2020-03-25        rkeene: 			continue;
eebfe1f40f 2020-03-25        rkeene: 		}
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 		stat_ret = stat(full_path_buf, &file_stat);
eebfe1f40f 2020-03-25        rkeene: 		if (stat_ret != 0) {
eebfe1f40f 2020-03-25        rkeene: 			continue;
eebfe1f40f 2020-03-25        rkeene: 		}
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 		children[child_idx] = strdup(file_info->d_name);
eebfe1f40f 2020-03-25        rkeene: 		child_idx++;
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 		if (S_ISDIR(file_stat.st_mode)) {
eebfe1f40f 2020-03-25        rkeene: 			parse_xvfs_minirivet_directory(outfp, xvfs_state, full_path_buf, rel_path_buf);
eebfe1f40f 2020-03-25        rkeene: 		} else {
eebfe1f40f 2020-03-25        rkeene: 			parse_xvfs_minirivet_file(outfp, full_path_buf, rel_path_buf);
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 			xvfs_state->children[xvfs_state->child_count] = strdup(rel_path_buf);
eebfe1f40f 2020-03-25        rkeene: 			xvfs_state->child_count++;
eebfe1f40f 2020-03-25        rkeene: 		}
eebfe1f40f 2020-03-25        rkeene: 	}
eebfe1f40f 2020-03-25        rkeene: 	free(full_path_buf);
eebfe1f40f 2020-03-25        rkeene: 	free(rel_path_buf);
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 	child_count = child_idx;
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 	fprintf(outfp, "\t{\n");
eebfe1f40f 2020-03-25        rkeene: 	fprintf(outfp, "\t\t.name = \"%s\",\n", prefix);
eebfe1f40f 2020-03-25        rkeene: 	fprintf(outfp, "\t\t.type = XVFS_FILE_TYPE_DIR,\n");
eebfe1f40f 2020-03-25        rkeene: 	fprintf(outfp, "\t\t.data.dirChildren  = (const char *[]) {");
eebfe1f40f 2020-03-25        rkeene: 	for (child_idx = 0; child_idx < child_count; child_idx++) {
eebfe1f40f 2020-03-25        rkeene: 		if (child_idx != 0) {
eebfe1f40f 2020-03-25        rkeene: 			fprintf(outfp, ", ");
eebfe1f40f 2020-03-25        rkeene: 		}
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 		fprintf(outfp, "\"%s\"", children[child_idx]);
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 		free(children[child_idx]);
eebfe1f40f 2020-03-25        rkeene: 	}
eebfe1f40f 2020-03-25        rkeene: 	fprintf(outfp, "},\n");
eebfe1f40f 2020-03-25        rkeene: 	fprintf(outfp, "\t\t.size = %lu\n", child_count);
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 	free(children);
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 	fprintf(outfp, "\t},\n");
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 	xvfs_state->children[xvfs_state->child_count] = strdup(prefix);
eebfe1f40f 2020-03-25        rkeene: 	xvfs_state->child_count++;
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 	closedir(dp);
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 	return;
eebfe1f40f 2020-03-25        rkeene: }
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: static void parse_xvfs_minirivet_hashtable_header(FILE *outfp, struct xvfs_state *xvfs_state) {
eebfe1f40f 2020-03-25        rkeene: 	const int max_bucket_count = 30;
eebfe1f40f 2020-03-25        rkeene: 	int bucket_count;
eebfe1f40f 2020-03-25        rkeene: 	int idx1, idx2;
eebfe1f40f 2020-03-25        rkeene: 	int check_hash;
eebfe1f40f 2020-03-25        rkeene: 	int first_entry;
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 	if (xvfs_state->child_count > max_bucket_count) {
eebfe1f40f 2020-03-25        rkeene: 		bucket_count = max_bucket_count;
eebfe1f40f 2020-03-25        rkeene: 	} else {
eebfe1f40f 2020-03-25        rkeene: 		bucket_count = xvfs_state->child_count;
eebfe1f40f 2020-03-25        rkeene: 	}
eebfe1f40f 2020-03-25        rkeene: 	xvfs_state->bucket_count = bucket_count;
eebfe1f40f 2020-03-25        rkeene: 	xvfs_state->max_index = xvfs_state->child_count;
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 	fprintf(outfp, "\tlong pathIndex_idx;\n");
eebfe1f40f 2020-03-25        rkeene: 	fprintf(outfp, "\tint pathIndex_hash;\n");
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 	/*
eebfe1f40f 2020-03-25        rkeene: 	 * XXX:TODO: Make this not O(n^2)
eebfe1f40f 2020-03-25        rkeene: 	 */
eebfe1f40f 2020-03-25        rkeene: 	for (idx1 = 0; idx1 < bucket_count; idx1++) {
eebfe1f40f 2020-03-25        rkeene: 		fprintf(outfp, "\tstatic const long pathIndex_hashTable_%i[] = {\n", idx1);
eebfe1f40f 2020-03-25        rkeene: 		fprintf(outfp, "\t\t");
eebfe1f40f 2020-03-25        rkeene: 		first_entry = 1;
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 		for (idx2 = 0; idx2 < xvfs_state->child_count; idx2++) {
eebfe1f40f 2020-03-25        rkeene: 			check_hash = adler32(0, (unsigned char *) xvfs_state->children[idx2], strlen(xvfs_state->children[idx2])) % bucket_count;
eebfe1f40f 2020-03-25        rkeene: 			if (check_hash != idx1) {
eebfe1f40f 2020-03-25        rkeene: 				continue;
eebfe1f40f 2020-03-25        rkeene: 			}
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 			if (!first_entry) {
eebfe1f40f 2020-03-25        rkeene: 				fprintf(outfp, ", ");
eebfe1f40f 2020-03-25        rkeene: 			}
eebfe1f40f 2020-03-25        rkeene: 			first_entry = 0;
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 			if (check_hash == idx1) {
eebfe1f40f 2020-03-25        rkeene: 				fprintf(outfp, "%i", idx2);
eebfe1f40f 2020-03-25        rkeene: 			}
eebfe1f40f 2020-03-25        rkeene: 		}
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 		if (!first_entry) {
eebfe1f40f 2020-03-25        rkeene: 			fprintf(outfp, ", ");
eebfe1f40f 2020-03-25        rkeene: 		}
eebfe1f40f 2020-03-25        rkeene: 		fprintf(outfp, "XVFS_NAME_LOOKUP_ERROR");
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 		fprintf(outfp, "\n");
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 		fprintf(outfp, "\t};\n");
eebfe1f40f 2020-03-25        rkeene: 	}
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 	for (idx2 = 0; idx2 < xvfs_state->child_count; idx2++) {
eebfe1f40f 2020-03-25        rkeene: 		free(xvfs_state->children[idx2]);
eebfe1f40f 2020-03-25        rkeene: 	}
eebfe1f40f 2020-03-25        rkeene: 	free(xvfs_state->children);
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 	fprintf(outfp, "\tstatic const long * const pathIndex_hashTable[%i] = {\n", bucket_count);
eebfe1f40f 2020-03-25        rkeene: 	for (idx1 = 0; idx1 < bucket_count; idx1++) {
eebfe1f40f 2020-03-25        rkeene: 		fprintf(outfp, "\t\tpathIndex_hashTable_%i,\n", idx1);
eebfe1f40f 2020-03-25        rkeene: 	}
eebfe1f40f 2020-03-25        rkeene: 	fprintf(outfp, "\t};\n");
eebfe1f40f 2020-03-25        rkeene: 	return;
eebfe1f40f 2020-03-25        rkeene: }
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: static void parse_xvfs_minirivet_hashtable_body(FILE *outfp, struct xvfs_state *xvfs_state) {
eebfe1f40f 2020-03-25        rkeene: 	fprintf(outfp, "\tpathIndex_hash = Tcl_ZlibAdler32(0, (unsigned char *) path, pathLen) %% %i;\n", xvfs_state->bucket_count);
eebfe1f40f 2020-03-25        rkeene: 	fprintf(outfp, "\tfor (pathIndex_idx = 0; pathIndex_idx < %i; pathIndex_idx++) {\n", xvfs_state->max_index);
eebfe1f40f 2020-03-25        rkeene: 	fprintf(outfp, "\t\tpathIndex = pathIndex_hashTable[pathIndex_hash][pathIndex_idx];\n");
eebfe1f40f 2020-03-25        rkeene: 	fprintf(outfp, "\t\tif (pathIndex == XVFS_NAME_LOOKUP_ERROR) {\n");
eebfe1f40f 2020-03-25        rkeene: 	fprintf(outfp, "\t\t\tbreak;\n");
eebfe1f40f 2020-03-25        rkeene: 	fprintf(outfp, "\t\t}\n");
eebfe1f40f 2020-03-25        rkeene: 	fprintf(outfp, "\n");
eebfe1f40f 2020-03-25        rkeene: 	fprintf(outfp, "\t\tif (strcmp(path, xvfs_example_data[pathIndex].name) == 0) {\n");
eebfe1f40f 2020-03-25        rkeene: 	fprintf(outfp, "\t\t\treturn(pathIndex);\n");
eebfe1f40f 2020-03-25        rkeene: 	fprintf(outfp, "\t\t}\n");
eebfe1f40f 2020-03-25        rkeene: 	fprintf(outfp, "\t}\n");
eebfe1f40f 2020-03-25        rkeene: 	return;
eebfe1f40f 2020-03-25        rkeene: }
eebfe1f40f 2020-03-25        rkeene: 
160dcdcda4 2020-04-03        rkeene: static void parse_xvfs_minirivet_handle_tcl_print(FILE *outfp, const struct xvfs_options * const options, struct xvfs_state *xvfs_state, char *command) {
eebfe1f40f 2020-03-25        rkeene: 	char *buffer_p, *buffer_e;
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 	buffer_p = command;
eebfe1f40f 2020-03-25        rkeene: 	while (*buffer_p && isspace(*buffer_p)) {
eebfe1f40f 2020-03-25        rkeene: 		buffer_p++;
eebfe1f40f 2020-03-25        rkeene: 	}
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 	buffer_e = buffer_p + strlen(buffer_p) - 1;
eebfe1f40f 2020-03-25        rkeene: 	while (buffer_e >= buffer_p && isspace(*buffer_e)) {
eebfe1f40f 2020-03-25        rkeene: 		*buffer_e = '\0';
eebfe1f40f 2020-03-25        rkeene: 		buffer_e--;
eebfe1f40f 2020-03-25        rkeene: 	}
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 	if (strcmp(buffer_p, "$::xvfs::fsName") == 0) {
eebfe1f40f 2020-03-25        rkeene: 		fprintf(outfp, "%s", options->name);
eebfe1f40f 2020-03-25        rkeene: 	} else if (strcmp(buffer_p, "$::xvfs::fileInfoStruct") == 0) {
eebfe1f40f 2020-03-25        rkeene: 		fprintf(outfp, "static const struct xvfs_file_data xvfs_");
eebfe1f40f 2020-03-25        rkeene: 		fprintf(outfp, "%s", options->name);
eebfe1f40f 2020-03-25        rkeene: 		fprintf(outfp, "_data[] = {\n");
eebfe1f40f 2020-03-25        rkeene: 		parse_xvfs_minirivet_directory(outfp, xvfs_state, options->directory, "");
eebfe1f40f 2020-03-25        rkeene: 		fprintf(outfp, "};\n");
eebfe1f40f 2020-03-25        rkeene: 	} else if (strcmp(buffer_p, "[zlib adler32 $::xvfs::fsName 0]") == 0) {
eebfe1f40f 2020-03-25        rkeene: 		fprintf(outfp, "%lu", adler32(0, (unsigned char *) options->name, strlen(options->name)));
eebfe1f40f 2020-03-25        rkeene: 	} else if (strcmp(buffer_p, "$hashTableHeader") == 0) {
eebfe1f40f 2020-03-25        rkeene: 		parse_xvfs_minirivet_hashtable_header(outfp, xvfs_state);
eebfe1f40f 2020-03-25        rkeene: 	} else if (strcmp(buffer_p, "[dict get $hashTable body]") == 0) {
eebfe1f40f 2020-03-25        rkeene: 		parse_xvfs_minirivet_hashtable_body(outfp, xvfs_state);
eebfe1f40f 2020-03-25        rkeene: 	} else {
eebfe1f40f 2020-03-25        rkeene: 		fprintf(outfp, "@INVALID@%s@INVALID@", buffer_p);
eebfe1f40f 2020-03-25        rkeene: 	}
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 	return;
eebfe1f40f 2020-03-25        rkeene: }
eebfe1f40f 2020-03-25        rkeene: 
160dcdcda4 2020-04-03        rkeene: static int parse_xvfs_minirivet(FILE *outfp, const char * const template, const struct xvfs_options * const options) {
eebfe1f40f 2020-03-25        rkeene: 	struct xvfs_state xvfs_state;
eebfe1f40f 2020-03-25        rkeene: 	int ch, ch_buf;
eebfe1f40f 2020-03-25        rkeene: 	int template_idx = 0;
eebfe1f40f 2020-03-25        rkeene: 	char tcl_buffer[8192], *tcl_buffer_p;
eebfe1f40f 2020-03-25        rkeene: 	enum xvfs_minirivet_mode mode;
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 	xvfs_state.child_count = 0;
eebfe1f40f 2020-03-25        rkeene: 	xvfs_state.child_len   = 65536;
eebfe1f40f 2020-03-25        rkeene: 	xvfs_state.children    = malloc(sizeof(*xvfs_state.children) * xvfs_state.child_len);
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: #define parse_xvfs_minirivet_getbyte(var) var = template[template_idx]; template_idx++; if (var == 0) { break; }
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 	mode = XVFS_MINIRIVET_MODE_COPY;
eebfe1f40f 2020-03-25        rkeene: 	tcl_buffer_p = NULL;
eebfe1f40f 2020-03-25        rkeene: 	while (1) {
eebfe1f40f 2020-03-25        rkeene: 		parse_xvfs_minirivet_getbyte(ch);
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 		switch (mode) {
eebfe1f40f 2020-03-25        rkeene: 			case XVFS_MINIRIVET_MODE_COPY:
eebfe1f40f 2020-03-25        rkeene: 				if (ch == '<') {
eebfe1f40f 2020-03-25        rkeene: 					parse_xvfs_minirivet_getbyte(ch_buf);
eebfe1f40f 2020-03-25        rkeene: 					if (ch_buf != '?') {
eebfe1f40f 2020-03-25        rkeene: 						fputc('<', outfp);
eebfe1f40f 2020-03-25        rkeene: 						ch = ch_buf;
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 						break;
eebfe1f40f 2020-03-25        rkeene: 					}
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 					tcl_buffer_p = tcl_buffer;
eebfe1f40f 2020-03-25        rkeene: 					parse_xvfs_minirivet_getbyte(ch_buf);
eebfe1f40f 2020-03-25        rkeene: 					if (ch_buf == '=') {
eebfe1f40f 2020-03-25        rkeene: 						mode = XVFS_MINIRIVET_MODE_TCL_PRINT;
eebfe1f40f 2020-03-25        rkeene: 					} else {
eebfe1f40f 2020-03-25        rkeene: 						mode = XVFS_MINIRIVET_MODE_TCL;
eebfe1f40f 2020-03-25        rkeene: 						*tcl_buffer_p = ch_buf;
eebfe1f40f 2020-03-25        rkeene: 						tcl_buffer_p++;
eebfe1f40f 2020-03-25        rkeene: 					}
eebfe1f40f 2020-03-25        rkeene: 					*tcl_buffer_p = '\0';
eebfe1f40f 2020-03-25        rkeene: 					continue;
eebfe1f40f 2020-03-25        rkeene: 				}
eebfe1f40f 2020-03-25        rkeene: 				break;
eebfe1f40f 2020-03-25        rkeene: 			case XVFS_MINIRIVET_MODE_TCL:
eebfe1f40f 2020-03-25        rkeene: 			case XVFS_MINIRIVET_MODE_TCL_PRINT:
eebfe1f40f 2020-03-25        rkeene: 				if (ch == '?') {
eebfe1f40f 2020-03-25        rkeene: 					parse_xvfs_minirivet_getbyte(ch_buf);
eebfe1f40f 2020-03-25        rkeene: 					if (ch_buf != '>') {
eebfe1f40f 2020-03-25        rkeene: 						*tcl_buffer_p = ch;
eebfe1f40f 2020-03-25        rkeene: 						tcl_buffer_p++;
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 						ch = ch_buf;
eebfe1f40f 2020-03-25        rkeene: 						
eebfe1f40f 2020-03-25        rkeene: 						break;
eebfe1f40f 2020-03-25        rkeene: 					}
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 					*tcl_buffer_p = '\0';
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 					if (mode == XVFS_MINIRIVET_MODE_TCL_PRINT) {
eebfe1f40f 2020-03-25        rkeene: 						parse_xvfs_minirivet_handle_tcl_print(outfp, options, &xvfs_state, tcl_buffer);
eebfe1f40f 2020-03-25        rkeene: 					}
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 					mode = XVFS_MINIRIVET_MODE_COPY;
eebfe1f40f 2020-03-25        rkeene: 					continue;
eebfe1f40f 2020-03-25        rkeene: 				}
eebfe1f40f 2020-03-25        rkeene: 				break;
eebfe1f40f 2020-03-25        rkeene: 		}
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 		switch (mode) {
eebfe1f40f 2020-03-25        rkeene: 			case XVFS_MINIRIVET_MODE_COPY:
eebfe1f40f 2020-03-25        rkeene: 				fputc(ch, outfp);
eebfe1f40f 2020-03-25        rkeene: 				break;
eebfe1f40f 2020-03-25        rkeene: 			case XVFS_MINIRIVET_MODE_TCL:
eebfe1f40f 2020-03-25        rkeene: 			case XVFS_MINIRIVET_MODE_TCL_PRINT:
eebfe1f40f 2020-03-25        rkeene: 				*tcl_buffer_p = ch;
eebfe1f40f 2020-03-25        rkeene: 				tcl_buffer_p++;
eebfe1f40f 2020-03-25        rkeene: 				break;
eebfe1f40f 2020-03-25        rkeene: 		}
eebfe1f40f 2020-03-25        rkeene: 	}
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: #undef parse_xvfs_minirivet_getbyte
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 	return(1);
eebfe1f40f 2020-03-25        rkeene: }
eebfe1f40f 2020-03-25        rkeene: 
160dcdcda4 2020-04-03        rkeene: static int xvfs_create(FILE *outfp, const struct xvfs_options * const options) {
eebfe1f40f 2020-03-25        rkeene: 	const int template_len = 65536;
eebfe1f40f 2020-03-25        rkeene: 	const char * const template_file = "lib/xvfs/xvfs.c.rvt";
eebfe1f40f 2020-03-25        rkeene: 	FILE *fp;
eebfe1f40f 2020-03-25        rkeene: 	char *template, *template_p;
eebfe1f40f 2020-03-25        rkeene: 	int template_remain;
eebfe1f40f 2020-03-25        rkeene: 	size_t fread_ret;
eebfe1f40f 2020-03-25        rkeene: 	int retval;
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 	fp = fopen(template_file, "r");
eebfe1f40f 2020-03-25        rkeene: 	if (!fp) {
eebfe1f40f 2020-03-25        rkeene: 		return(0);
eebfe1f40f 2020-03-25        rkeene: 	}
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 	template = malloc(template_len);
eebfe1f40f 2020-03-25        rkeene: 	template_remain = template_len;
eebfe1f40f 2020-03-25        rkeene: 	if (!template) {
eebfe1f40f 2020-03-25        rkeene: 		fclose(fp);
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 		return(0);
eebfe1f40f 2020-03-25        rkeene: 	}
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 	template_p = template;
eebfe1f40f 2020-03-25        rkeene: 	while (1) {
eebfe1f40f 2020-03-25        rkeene: 		fread_ret = fread(template_p, 1, template_remain, fp);
eebfe1f40f 2020-03-25        rkeene: 		if (fread_ret <= 0) {
eebfe1f40f 2020-03-25        rkeene: 			break;
eebfe1f40f 2020-03-25        rkeene: 		}
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 		template_p += fread_ret;
eebfe1f40f 2020-03-25        rkeene: 		template_remain -= fread_ret;
eebfe1f40f 2020-03-25        rkeene: 	}
eebfe1f40f 2020-03-25        rkeene: 	if (template_remain > 0) {
eebfe1f40f 2020-03-25        rkeene: 		*template_p = '\0';
eebfe1f40f 2020-03-25        rkeene: 	}
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 	fclose(fp);
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 	retval = parse_xvfs_minirivet(outfp, template, options);
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 	free(template);
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 	return(retval);
eebfe1f40f 2020-03-25        rkeene: }
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: /*
eebfe1f40f 2020-03-25        rkeene:  * Parse command line options
eebfe1f40f 2020-03-25        rkeene:  */
160dcdcda4 2020-04-03        rkeene: static int parse_options(int argc, char **argv, struct xvfs_options *options) {
eebfe1f40f 2020-03-25        rkeene: 	char *arg;
eebfe1f40f 2020-03-25        rkeene: 	char **option;
eebfe1f40f 2020-03-25        rkeene: 	int idx;
eebfe1f40f 2020-03-25        rkeene: 	int retval;
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 	for (idx = 0; idx < argc; idx++) {
eebfe1f40f 2020-03-25        rkeene: 		arg = argv[idx];
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 		if (strcmp(arg, "--directory") == 0) {
eebfe1f40f 2020-03-25        rkeene: 			option = &options->directory;
eebfe1f40f 2020-03-25        rkeene: 		} else if (strcmp(arg, "--name") == 0) {
eebfe1f40f 2020-03-25        rkeene: 			option = &options->name;
eebfe1f40f 2020-03-25        rkeene: 		} else {
eebfe1f40f 2020-03-25        rkeene: 			fprintf(stderr, "Invalid argument %s\n", arg);
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 			return(0);
eebfe1f40f 2020-03-25        rkeene: 		}
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 		idx++;
eebfe1f40f 2020-03-25        rkeene: 		arg = argv[idx];
eebfe1f40f 2020-03-25        rkeene: 		*option = arg;
eebfe1f40f 2020-03-25        rkeene: 	}
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 	retval = 1;
eebfe1f40f 2020-03-25        rkeene: 	if (!options->directory) {		
eebfe1f40f 2020-03-25        rkeene: 		fprintf(stderr, "error: --directory must be specified\n");
eebfe1f40f 2020-03-25        rkeene: 		retval = 0;
eebfe1f40f 2020-03-25        rkeene: 	}
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 	if (!options->name) {
eebfe1f40f 2020-03-25        rkeene: 		fprintf(stderr, "error: --name must be specified\n");
eebfe1f40f 2020-03-25        rkeene: 		retval = 0;
eebfe1f40f 2020-03-25        rkeene: 	}
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 	return(retval);
eebfe1f40f 2020-03-25        rkeene: }
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: int main(int argc, char **argv) {
160dcdcda4 2020-04-03        rkeene: 	struct xvfs_options options = {0};
eebfe1f40f 2020-03-25        rkeene: 	int parse_options_ret, xvfs_create_ret;
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 	argc--;
eebfe1f40f 2020-03-25        rkeene: 	argv++;
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 	parse_options_ret = parse_options(argc, argv, &options);
eebfe1f40f 2020-03-25        rkeene: 	if (!parse_options_ret) {
eebfe1f40f 2020-03-25        rkeene: 		return(1);
eebfe1f40f 2020-03-25        rkeene: 	}
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 	xvfs_create_ret = xvfs_create(stdout, &options);
eebfe1f40f 2020-03-25        rkeene: 	if (!xvfs_create_ret) {
eebfe1f40f 2020-03-25        rkeene: 		return(1);
eebfe1f40f 2020-03-25        rkeene: 	}
eebfe1f40f 2020-03-25        rkeene: 
eebfe1f40f 2020-03-25        rkeene: 	return(0);
eebfe1f40f 2020-03-25        rkeene: }