eebfe1f40f 2020-03-25 1: #include <sys/stat.h>
eebfe1f40f 2020-03-25 2: #include <stdlib.h>
eebfe1f40f 2020-03-25 3: #include <string.h>
eebfe1f40f 2020-03-25 4: #include <dirent.h>
eebfe1f40f 2020-03-25 5: #include <stdio.h>
eebfe1f40f 2020-03-25 6: #include <ctype.h>
eebfe1f40f 2020-03-25 7: #include <fcntl.h>
eebfe1f40f 2020-03-25 8:
160dcdcda4 2020-04-03 9: struct xvfs_options {
eebfe1f40f 2020-03-25 10: char *name;
eebfe1f40f 2020-03-25 11: char *directory;
eebfe1f40f 2020-03-25 12: };
eebfe1f40f 2020-03-25 13:
eebfe1f40f 2020-03-25 14: struct xvfs_state {
eebfe1f40f 2020-03-25 15: char **children;
eebfe1f40f 2020-03-25 16: unsigned long child_count;
eebfe1f40f 2020-03-25 17: unsigned long child_len;
eebfe1f40f 2020-03-25 18: int bucket_count;
eebfe1f40f 2020-03-25 19: int max_index;
eebfe1f40f 2020-03-25 20: };
eebfe1f40f 2020-03-25 21:
eebfe1f40f 2020-03-25 22: enum xvfs_minirivet_mode {
eebfe1f40f 2020-03-25 23: XVFS_MINIRIVET_MODE_COPY,
eebfe1f40f 2020-03-25 24: XVFS_MINIRIVET_MODE_TCL,
eebfe1f40f 2020-03-25 25: XVFS_MINIRIVET_MODE_TCL_PRINT
eebfe1f40f 2020-03-25 26: };
eebfe1f40f 2020-03-25 27:
eebfe1f40f 2020-03-25 28: /*
eebfe1f40f 2020-03-25 29: * adler32() function from zlib 1.1.4 and under the same license
eebfe1f40f 2020-03-25 30: */
eebfe1f40f 2020-03-25 31: static unsigned long adler32(unsigned long adler, const unsigned char *buf, unsigned int len) {
eebfe1f40f 2020-03-25 32: const int len_max = 5552;
eebfe1f40f 2020-03-25 33: const unsigned long base = 65521;
eebfe1f40f 2020-03-25 34: unsigned long s1 = adler & 0xffff;
eebfe1f40f 2020-03-25 35: unsigned long s2 = (adler >> 16) & 0xffff;
eebfe1f40f 2020-03-25 36: int k, i;
eebfe1f40f 2020-03-25 37:
eebfe1f40f 2020-03-25 38: if (buf == NULL) {
eebfe1f40f 2020-03-25 39: return(1UL);
eebfe1f40f 2020-03-25 40: }
eebfe1f40f 2020-03-25 41:
eebfe1f40f 2020-03-25 42: while (len > 0) {
eebfe1f40f 2020-03-25 43: k = len < len_max ? len : len_max;
eebfe1f40f 2020-03-25 44: len -= k;
eebfe1f40f 2020-03-25 45:
eebfe1f40f 2020-03-25 46: while (k >= 16) {
eebfe1f40f 2020-03-25 47: for (i = 0; i < 16; i++) {
eebfe1f40f 2020-03-25 48: s2 += buf[i];
eebfe1f40f 2020-03-25 49: }
eebfe1f40f 2020-03-25 50: s1 = buf[15];
eebfe1f40f 2020-03-25 51:
eebfe1f40f 2020-03-25 52: buf += 16;
eebfe1f40f 2020-03-25 53: k -= 16;
eebfe1f40f 2020-03-25 54: }
eebfe1f40f 2020-03-25 55:
eebfe1f40f 2020-03-25 56: if (k != 0) {
eebfe1f40f 2020-03-25 57: do {
eebfe1f40f 2020-03-25 58: s1 += *buf++;
eebfe1f40f 2020-03-25 59: s2 += s1;
eebfe1f40f 2020-03-25 60: } while (--k);
eebfe1f40f 2020-03-25 61: }
eebfe1f40f 2020-03-25 62:
eebfe1f40f 2020-03-25 63: s1 %= base;
eebfe1f40f 2020-03-25 64: s2 %= base;
eebfe1f40f 2020-03-25 65: }
eebfe1f40f 2020-03-25 66:
eebfe1f40f 2020-03-25 67: return((s2 << 16) | s1);
eebfe1f40f 2020-03-25 68: }
eebfe1f40f 2020-03-25 69:
eebfe1f40f 2020-03-25 70: /*
eebfe1f40f 2020-03-25 71: * Handle XVFS Rivet template file substitution
eebfe1f40f 2020-03-25 72: */
eebfe1f40f 2020-03-25 73: static void parse_xvfs_minirivet_file(FILE *outfp, const char * const external_file_name, const char * const internal_file_name) {
eebfe1f40f 2020-03-25 74: FILE *fp;
eebfe1f40f 2020-03-25 75: unsigned long file_size;
eebfe1f40f 2020-03-25 76: unsigned char buf[10];
eebfe1f40f 2020-03-25 77: size_t item_count;
eebfe1f40f 2020-03-25 78: int idx;
eebfe1f40f 2020-03-25 79:
eebfe1f40f 2020-03-25 80: fp = fopen(external_file_name, "rb");
eebfe1f40f 2020-03-25 81: if (!fp) {
eebfe1f40f 2020-03-25 82: return;
eebfe1f40f 2020-03-25 83: }
eebfe1f40f 2020-03-25 84:
eebfe1f40f 2020-03-25 85: fprintf(outfp, "\t{\n");
eebfe1f40f 2020-03-25 86: fprintf(outfp, "\t\t.name = \"%s\",\n", internal_file_name);
eebfe1f40f 2020-03-25 87: fprintf(outfp, "\t\t.type = XVFS_FILE_TYPE_REG,\n");
eebfe1f40f 2020-03-25 88: fprintf(outfp, "\t\t.data.fileContents = (const unsigned char *) \"");
eebfe1f40f 2020-03-25 89:
eebfe1f40f 2020-03-25 90: file_size = 0;
eebfe1f40f 2020-03-25 91: while (1) {
eebfe1f40f 2020-03-25 92: item_count = fread(&buf, 1, sizeof(buf), fp);
eebfe1f40f 2020-03-25 93: if (item_count <= 0) {
eebfe1f40f 2020-03-25 94: break;
eebfe1f40f 2020-03-25 95: }
eebfe1f40f 2020-03-25 96:
eebfe1f40f 2020-03-25 97: if (file_size != 0) {
eebfe1f40f 2020-03-25 98: fprintf(outfp, "\n\t\t\t\"");
eebfe1f40f 2020-03-25 99: }
eebfe1f40f 2020-03-25 100:
eebfe1f40f 2020-03-25 101: for (idx = 0; idx < item_count; idx++) {
eebfe1f40f 2020-03-25 102: fprintf(outfp, "\\x%02x", (int) buf[idx]);
eebfe1f40f 2020-03-25 103: }
eebfe1f40f 2020-03-25 104: fprintf(outfp, "\"");
eebfe1f40f 2020-03-25 105:
eebfe1f40f 2020-03-25 106: file_size += item_count;
eebfe1f40f 2020-03-25 107: }
eebfe1f40f 2020-03-25 108:
eebfe1f40f 2020-03-25 109: fclose(fp);
eebfe1f40f 2020-03-25 110:
eebfe1f40f 2020-03-25 111: fprintf(outfp, ",\n");
eebfe1f40f 2020-03-25 112: fprintf(outfp, "\t\t.size = %lu\n", file_size);
eebfe1f40f 2020-03-25 113: fprintf(outfp, "\t},\n");
eebfe1f40f 2020-03-25 114: }
eebfe1f40f 2020-03-25 115:
eebfe1f40f 2020-03-25 116: 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 117: const unsigned int max_path_len = 8192, max_children = 65536;
eebfe1f40f 2020-03-25 118: unsigned long child_idx, child_count;
eebfe1f40f 2020-03-25 119: DIR *dp;
eebfe1f40f 2020-03-25 120: struct dirent *file_info;
eebfe1f40f 2020-03-25 121: struct stat file_stat;
eebfe1f40f 2020-03-25 122: char *full_path_buf;
eebfe1f40f 2020-03-25 123: char *rel_path_buf;
eebfe1f40f 2020-03-25 124: char **children;
eebfe1f40f 2020-03-25 125: int stat_ret;
eebfe1f40f 2020-03-25 126: int snprintf_ret;
eebfe1f40f 2020-03-25 127:
eebfe1f40f 2020-03-25 128: dp = opendir(directory);
eebfe1f40f 2020-03-25 129: if (!dp) {
eebfe1f40f 2020-03-25 130: return;
eebfe1f40f 2020-03-25 131: }
eebfe1f40f 2020-03-25 132:
eebfe1f40f 2020-03-25 133: full_path_buf = malloc(max_path_len);
eebfe1f40f 2020-03-25 134: rel_path_buf = malloc(max_path_len);
eebfe1f40f 2020-03-25 135: children = malloc(sizeof(*children) * max_children);
eebfe1f40f 2020-03-25 136:
eebfe1f40f 2020-03-25 137: child_idx = 0;
eebfe1f40f 2020-03-25 138: while (1) {
eebfe1f40f 2020-03-25 139: file_info = readdir(dp);
eebfe1f40f 2020-03-25 140: if (!file_info) {
eebfe1f40f 2020-03-25 141: break;
eebfe1f40f 2020-03-25 142: }
eebfe1f40f 2020-03-25 143:
eebfe1f40f 2020-03-25 144: if (strcmp(file_info->d_name, ".") == 0) {
eebfe1f40f 2020-03-25 145: continue;
eebfe1f40f 2020-03-25 146: }
eebfe1f40f 2020-03-25 147:
eebfe1f40f 2020-03-25 148: if (strcmp(file_info->d_name, "..") == 0) {
eebfe1f40f 2020-03-25 149: continue;
eebfe1f40f 2020-03-25 150: }
eebfe1f40f 2020-03-25 151:
eebfe1f40f 2020-03-25 152: snprintf_ret = snprintf(full_path_buf, max_path_len, "%s/%s", directory, file_info->d_name);
eebfe1f40f 2020-03-25 153: if (snprintf_ret >= max_path_len) {
eebfe1f40f 2020-03-25 154: continue;
eebfe1f40f 2020-03-25 155: }
eebfe1f40f 2020-03-25 156:
eebfe1f40f 2020-03-25 157: snprintf_ret = snprintf(rel_path_buf, max_path_len, "%s%s%s",
eebfe1f40f 2020-03-25 158: prefix,
eebfe1f40f 2020-03-25 159: strcmp(prefix, "") == 0 ? "" : "/",
eebfe1f40f 2020-03-25 160: file_info->d_name
eebfe1f40f 2020-03-25 161: );
eebfe1f40f 2020-03-25 162: if (snprintf_ret >= max_path_len) {
eebfe1f40f 2020-03-25 163: continue;
eebfe1f40f 2020-03-25 164: }
eebfe1f40f 2020-03-25 165:
eebfe1f40f 2020-03-25 166: stat_ret = stat(full_path_buf, &file_stat);
eebfe1f40f 2020-03-25 167: if (stat_ret != 0) {
eebfe1f40f 2020-03-25 168: continue;
eebfe1f40f 2020-03-25 169: }
eebfe1f40f 2020-03-25 170:
eebfe1f40f 2020-03-25 171: children[child_idx] = strdup(file_info->d_name);
eebfe1f40f 2020-03-25 172: child_idx++;
eebfe1f40f 2020-03-25 173:
eebfe1f40f 2020-03-25 174: if (S_ISDIR(file_stat.st_mode)) {
eebfe1f40f 2020-03-25 175: parse_xvfs_minirivet_directory(outfp, xvfs_state, full_path_buf, rel_path_buf);
eebfe1f40f 2020-03-25 176: } else {
eebfe1f40f 2020-03-25 177: parse_xvfs_minirivet_file(outfp, full_path_buf, rel_path_buf);
eebfe1f40f 2020-03-25 178:
eebfe1f40f 2020-03-25 179: xvfs_state->children[xvfs_state->child_count] = strdup(rel_path_buf);
eebfe1f40f 2020-03-25 180: xvfs_state->child_count++;
eebfe1f40f 2020-03-25 181: }
eebfe1f40f 2020-03-25 182: }
eebfe1f40f 2020-03-25 183: free(full_path_buf);
eebfe1f40f 2020-03-25 184: free(rel_path_buf);
eebfe1f40f 2020-03-25 185:
eebfe1f40f 2020-03-25 186: child_count = child_idx;
eebfe1f40f 2020-03-25 187:
eebfe1f40f 2020-03-25 188: fprintf(outfp, "\t{\n");
eebfe1f40f 2020-03-25 189: fprintf(outfp, "\t\t.name = \"%s\",\n", prefix);
eebfe1f40f 2020-03-25 190: fprintf(outfp, "\t\t.type = XVFS_FILE_TYPE_DIR,\n");
eebfe1f40f 2020-03-25 191: fprintf(outfp, "\t\t.data.dirChildren = (const char *[]) {");
eebfe1f40f 2020-03-25 192: for (child_idx = 0; child_idx < child_count; child_idx++) {
eebfe1f40f 2020-03-25 193: if (child_idx != 0) {
eebfe1f40f 2020-03-25 194: fprintf(outfp, ", ");
eebfe1f40f 2020-03-25 195: }
eebfe1f40f 2020-03-25 196:
eebfe1f40f 2020-03-25 197: fprintf(outfp, "\"%s\"", children[child_idx]);
eebfe1f40f 2020-03-25 198:
eebfe1f40f 2020-03-25 199: free(children[child_idx]);
eebfe1f40f 2020-03-25 200: }
eebfe1f40f 2020-03-25 201: fprintf(outfp, "},\n");
eebfe1f40f 2020-03-25 202: fprintf(outfp, "\t\t.size = %lu\n", child_count);
eebfe1f40f 2020-03-25 203:
eebfe1f40f 2020-03-25 204: free(children);
eebfe1f40f 2020-03-25 205:
eebfe1f40f 2020-03-25 206: fprintf(outfp, "\t},\n");
eebfe1f40f 2020-03-25 207:
eebfe1f40f 2020-03-25 208: xvfs_state->children[xvfs_state->child_count] = strdup(prefix);
eebfe1f40f 2020-03-25 209: xvfs_state->child_count++;
eebfe1f40f 2020-03-25 210:
eebfe1f40f 2020-03-25 211: closedir(dp);
eebfe1f40f 2020-03-25 212:
eebfe1f40f 2020-03-25 213: return;
eebfe1f40f 2020-03-25 214: }
eebfe1f40f 2020-03-25 215:
eebfe1f40f 2020-03-25 216: static void parse_xvfs_minirivet_hashtable_header(FILE *outfp, struct xvfs_state *xvfs_state) {
eebfe1f40f 2020-03-25 217: const int max_bucket_count = 30;
eebfe1f40f 2020-03-25 218: int bucket_count;
eebfe1f40f 2020-03-25 219: int idx1, idx2;
eebfe1f40f 2020-03-25 220: int check_hash;
eebfe1f40f 2020-03-25 221: int first_entry;
eebfe1f40f 2020-03-25 222:
eebfe1f40f 2020-03-25 223: if (xvfs_state->child_count > max_bucket_count) {
eebfe1f40f 2020-03-25 224: bucket_count = max_bucket_count;
eebfe1f40f 2020-03-25 225: } else {
eebfe1f40f 2020-03-25 226: bucket_count = xvfs_state->child_count;
eebfe1f40f 2020-03-25 227: }
eebfe1f40f 2020-03-25 228: xvfs_state->bucket_count = bucket_count;
eebfe1f40f 2020-03-25 229: xvfs_state->max_index = xvfs_state->child_count;
eebfe1f40f 2020-03-25 230:
eebfe1f40f 2020-03-25 231: fprintf(outfp, "\tlong pathIndex_idx;\n");
eebfe1f40f 2020-03-25 232: fprintf(outfp, "\tint pathIndex_hash;\n");
eebfe1f40f 2020-03-25 233:
eebfe1f40f 2020-03-25 234: /*
eebfe1f40f 2020-03-25 235: * XXX:TODO: Make this not O(n^2)
eebfe1f40f 2020-03-25 236: */
eebfe1f40f 2020-03-25 237: for (idx1 = 0; idx1 < bucket_count; idx1++) {
eebfe1f40f 2020-03-25 238: fprintf(outfp, "\tstatic const long pathIndex_hashTable_%i[] = {\n", idx1);
eebfe1f40f 2020-03-25 239: fprintf(outfp, "\t\t");
eebfe1f40f 2020-03-25 240: first_entry = 1;
eebfe1f40f 2020-03-25 241:
eebfe1f40f 2020-03-25 242: for (idx2 = 0; idx2 < xvfs_state->child_count; idx2++) {
eebfe1f40f 2020-03-25 243: check_hash = adler32(0, (unsigned char *) xvfs_state->children[idx2], strlen(xvfs_state->children[idx2])) % bucket_count;
eebfe1f40f 2020-03-25 244: if (check_hash != idx1) {
eebfe1f40f 2020-03-25 245: continue;
eebfe1f40f 2020-03-25 246: }
eebfe1f40f 2020-03-25 247:
eebfe1f40f 2020-03-25 248: if (!first_entry) {
eebfe1f40f 2020-03-25 249: fprintf(outfp, ", ");
eebfe1f40f 2020-03-25 250: }
eebfe1f40f 2020-03-25 251: first_entry = 0;
eebfe1f40f 2020-03-25 252:
eebfe1f40f 2020-03-25 253: if (check_hash == idx1) {
eebfe1f40f 2020-03-25 254: fprintf(outfp, "%i", idx2);
eebfe1f40f 2020-03-25 255: }
eebfe1f40f 2020-03-25 256: }
eebfe1f40f 2020-03-25 257:
eebfe1f40f 2020-03-25 258: if (!first_entry) {
eebfe1f40f 2020-03-25 259: fprintf(outfp, ", ");
eebfe1f40f 2020-03-25 260: }
eebfe1f40f 2020-03-25 261: fprintf(outfp, "XVFS_NAME_LOOKUP_ERROR");
eebfe1f40f 2020-03-25 262:
eebfe1f40f 2020-03-25 263: fprintf(outfp, "\n");
eebfe1f40f 2020-03-25 264:
eebfe1f40f 2020-03-25 265: fprintf(outfp, "\t};\n");
eebfe1f40f 2020-03-25 266: }
eebfe1f40f 2020-03-25 267:
eebfe1f40f 2020-03-25 268: for (idx2 = 0; idx2 < xvfs_state->child_count; idx2++) {
eebfe1f40f 2020-03-25 269: free(xvfs_state->children[idx2]);
eebfe1f40f 2020-03-25 270: }
eebfe1f40f 2020-03-25 271: free(xvfs_state->children);
eebfe1f40f 2020-03-25 272:
eebfe1f40f 2020-03-25 273: fprintf(outfp, "\tstatic const long * const pathIndex_hashTable[%i] = {\n", bucket_count);
eebfe1f40f 2020-03-25 274: for (idx1 = 0; idx1 < bucket_count; idx1++) {
eebfe1f40f 2020-03-25 275: fprintf(outfp, "\t\tpathIndex_hashTable_%i,\n", idx1);
eebfe1f40f 2020-03-25 276: }
eebfe1f40f 2020-03-25 277: fprintf(outfp, "\t};\n");
eebfe1f40f 2020-03-25 278: return;
eebfe1f40f 2020-03-25 279: }
eebfe1f40f 2020-03-25 280:
eebfe1f40f 2020-03-25 281: static void parse_xvfs_minirivet_hashtable_body(FILE *outfp, struct xvfs_state *xvfs_state) {
eebfe1f40f 2020-03-25 282: fprintf(outfp, "\tpathIndex_hash = Tcl_ZlibAdler32(0, (unsigned char *) path, pathLen) %% %i;\n", xvfs_state->bucket_count);
eebfe1f40f 2020-03-25 283: fprintf(outfp, "\tfor (pathIndex_idx = 0; pathIndex_idx < %i; pathIndex_idx++) {\n", xvfs_state->max_index);
eebfe1f40f 2020-03-25 284: fprintf(outfp, "\t\tpathIndex = pathIndex_hashTable[pathIndex_hash][pathIndex_idx];\n");
eebfe1f40f 2020-03-25 285: fprintf(outfp, "\t\tif (pathIndex == XVFS_NAME_LOOKUP_ERROR) {\n");
eebfe1f40f 2020-03-25 286: fprintf(outfp, "\t\t\tbreak;\n");
eebfe1f40f 2020-03-25 287: fprintf(outfp, "\t\t}\n");
eebfe1f40f 2020-03-25 288: fprintf(outfp, "\n");
eebfe1f40f 2020-03-25 289: fprintf(outfp, "\t\tif (strcmp(path, xvfs_example_data[pathIndex].name) == 0) {\n");
eebfe1f40f 2020-03-25 290: fprintf(outfp, "\t\t\treturn(pathIndex);\n");
eebfe1f40f 2020-03-25 291: fprintf(outfp, "\t\t}\n");
eebfe1f40f 2020-03-25 292: fprintf(outfp, "\t}\n");
eebfe1f40f 2020-03-25 293: return;
eebfe1f40f 2020-03-25 294: }
eebfe1f40f 2020-03-25 295:
160dcdcda4 2020-04-03 296: 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 297: char *buffer_p, *buffer_e;
eebfe1f40f 2020-03-25 298:
eebfe1f40f 2020-03-25 299: buffer_p = command;
eebfe1f40f 2020-03-25 300: while (*buffer_p && isspace(*buffer_p)) {
eebfe1f40f 2020-03-25 301: buffer_p++;
eebfe1f40f 2020-03-25 302: }
eebfe1f40f 2020-03-25 303:
eebfe1f40f 2020-03-25 304: buffer_e = buffer_p + strlen(buffer_p) - 1;
eebfe1f40f 2020-03-25 305: while (buffer_e >= buffer_p && isspace(*buffer_e)) {
eebfe1f40f 2020-03-25 306: *buffer_e = '\0';
eebfe1f40f 2020-03-25 307: buffer_e--;
eebfe1f40f 2020-03-25 308: }
eebfe1f40f 2020-03-25 309:
eebfe1f40f 2020-03-25 310: if (strcmp(buffer_p, "$::xvfs::fsName") == 0) {
eebfe1f40f 2020-03-25 311: fprintf(outfp, "%s", options->name);
eebfe1f40f 2020-03-25 312: } else if (strcmp(buffer_p, "$::xvfs::fileInfoStruct") == 0) {
eebfe1f40f 2020-03-25 313: fprintf(outfp, "static const struct xvfs_file_data xvfs_");
eebfe1f40f 2020-03-25 314: fprintf(outfp, "%s", options->name);
eebfe1f40f 2020-03-25 315: fprintf(outfp, "_data[] = {\n");
eebfe1f40f 2020-03-25 316: parse_xvfs_minirivet_directory(outfp, xvfs_state, options->directory, "");
eebfe1f40f 2020-03-25 317: fprintf(outfp, "};\n");
eebfe1f40f 2020-03-25 318: } else if (strcmp(buffer_p, "[zlib adler32 $::xvfs::fsName 0]") == 0) {
eebfe1f40f 2020-03-25 319: fprintf(outfp, "%lu", adler32(0, (unsigned char *) options->name, strlen(options->name)));
5aadfc2b05 2020-04-13 320: } else if (strcmp(buffer_p, "[llength $::xvfs::outputFiles]") == 0) {
5aadfc2b05 2020-04-13 321: fprintf(outfp, "%lu", xvfs_state->child_count);
eebfe1f40f 2020-03-25 322: } else if (strcmp(buffer_p, "$hashTableHeader") == 0) {
eebfe1f40f 2020-03-25 323: parse_xvfs_minirivet_hashtable_header(outfp, xvfs_state);
eebfe1f40f 2020-03-25 324: } else if (strcmp(buffer_p, "[dict get $hashTable body]") == 0) {
eebfe1f40f 2020-03-25 325: parse_xvfs_minirivet_hashtable_body(outfp, xvfs_state);
eebfe1f40f 2020-03-25 326: } else {
eebfe1f40f 2020-03-25 327: fprintf(outfp, "@INVALID@%s@INVALID@", buffer_p);
eebfe1f40f 2020-03-25 328: }
eebfe1f40f 2020-03-25 329:
eebfe1f40f 2020-03-25 330: return;
eebfe1f40f 2020-03-25 331: }
eebfe1f40f 2020-03-25 332:
160dcdcda4 2020-04-03 333: static int parse_xvfs_minirivet(FILE *outfp, const char * const template, const struct xvfs_options * const options) {
eebfe1f40f 2020-03-25 334: struct xvfs_state xvfs_state;
eebfe1f40f 2020-03-25 335: int ch, ch_buf;
eebfe1f40f 2020-03-25 336: int template_idx = 0;
eebfe1f40f 2020-03-25 337: char tcl_buffer[8192], *tcl_buffer_p;
eebfe1f40f 2020-03-25 338: enum xvfs_minirivet_mode mode;
eebfe1f40f 2020-03-25 339:
eebfe1f40f 2020-03-25 340: xvfs_state.child_count = 0;
eebfe1f40f 2020-03-25 341: xvfs_state.child_len = 65536;
eebfe1f40f 2020-03-25 342: xvfs_state.children = malloc(sizeof(*xvfs_state.children) * xvfs_state.child_len);
eebfe1f40f 2020-03-25 343:
eebfe1f40f 2020-03-25 344: #define parse_xvfs_minirivet_getbyte(var) var = template[template_idx]; template_idx++; if (var == 0) { break; }
eebfe1f40f 2020-03-25 345:
eebfe1f40f 2020-03-25 346: mode = XVFS_MINIRIVET_MODE_COPY;
eebfe1f40f 2020-03-25 347: tcl_buffer_p = NULL;
eebfe1f40f 2020-03-25 348: while (1) {
eebfe1f40f 2020-03-25 349: parse_xvfs_minirivet_getbyte(ch);
eebfe1f40f 2020-03-25 350:
eebfe1f40f 2020-03-25 351: switch (mode) {
eebfe1f40f 2020-03-25 352: case XVFS_MINIRIVET_MODE_COPY:
eebfe1f40f 2020-03-25 353: if (ch == '<') {
eebfe1f40f 2020-03-25 354: parse_xvfs_minirivet_getbyte(ch_buf);
eebfe1f40f 2020-03-25 355: if (ch_buf != '?') {
eebfe1f40f 2020-03-25 356: fputc('<', outfp);
eebfe1f40f 2020-03-25 357: ch = ch_buf;
eebfe1f40f 2020-03-25 358:
eebfe1f40f 2020-03-25 359: break;
eebfe1f40f 2020-03-25 360: }
eebfe1f40f 2020-03-25 361:
eebfe1f40f 2020-03-25 362: tcl_buffer_p = tcl_buffer;
eebfe1f40f 2020-03-25 363: parse_xvfs_minirivet_getbyte(ch_buf);
eebfe1f40f 2020-03-25 364: if (ch_buf == '=') {
eebfe1f40f 2020-03-25 365: mode = XVFS_MINIRIVET_MODE_TCL_PRINT;
eebfe1f40f 2020-03-25 366: } else {
eebfe1f40f 2020-03-25 367: mode = XVFS_MINIRIVET_MODE_TCL;
eebfe1f40f 2020-03-25 368: *tcl_buffer_p = ch_buf;
eebfe1f40f 2020-03-25 369: tcl_buffer_p++;
eebfe1f40f 2020-03-25 370: }
eebfe1f40f 2020-03-25 371: *tcl_buffer_p = '\0';
eebfe1f40f 2020-03-25 372: continue;
eebfe1f40f 2020-03-25 373: }
eebfe1f40f 2020-03-25 374: break;
eebfe1f40f 2020-03-25 375: case XVFS_MINIRIVET_MODE_TCL:
eebfe1f40f 2020-03-25 376: case XVFS_MINIRIVET_MODE_TCL_PRINT:
eebfe1f40f 2020-03-25 377: if (ch == '?') {
eebfe1f40f 2020-03-25 378: parse_xvfs_minirivet_getbyte(ch_buf);
eebfe1f40f 2020-03-25 379: if (ch_buf != '>') {
eebfe1f40f 2020-03-25 380: *tcl_buffer_p = ch;
eebfe1f40f 2020-03-25 381: tcl_buffer_p++;
eebfe1f40f 2020-03-25 382:
eebfe1f40f 2020-03-25 383: ch = ch_buf;
eebfe1f40f 2020-03-25 384:
eebfe1f40f 2020-03-25 385: break;
eebfe1f40f 2020-03-25 386: }
eebfe1f40f 2020-03-25 387:
eebfe1f40f 2020-03-25 388: *tcl_buffer_p = '\0';
eebfe1f40f 2020-03-25 389:
eebfe1f40f 2020-03-25 390: if (mode == XVFS_MINIRIVET_MODE_TCL_PRINT) {
eebfe1f40f 2020-03-25 391: parse_xvfs_minirivet_handle_tcl_print(outfp, options, &xvfs_state, tcl_buffer);
eebfe1f40f 2020-03-25 392: }
eebfe1f40f 2020-03-25 393:
eebfe1f40f 2020-03-25 394: mode = XVFS_MINIRIVET_MODE_COPY;
eebfe1f40f 2020-03-25 395: continue;
eebfe1f40f 2020-03-25 396: }
eebfe1f40f 2020-03-25 397: break;
eebfe1f40f 2020-03-25 398: }
eebfe1f40f 2020-03-25 399:
eebfe1f40f 2020-03-25 400: switch (mode) {
eebfe1f40f 2020-03-25 401: case XVFS_MINIRIVET_MODE_COPY:
eebfe1f40f 2020-03-25 402: fputc(ch, outfp);
eebfe1f40f 2020-03-25 403: break;
eebfe1f40f 2020-03-25 404: case XVFS_MINIRIVET_MODE_TCL:
eebfe1f40f 2020-03-25 405: case XVFS_MINIRIVET_MODE_TCL_PRINT:
eebfe1f40f 2020-03-25 406: *tcl_buffer_p = ch;
eebfe1f40f 2020-03-25 407: tcl_buffer_p++;
eebfe1f40f 2020-03-25 408: break;
eebfe1f40f 2020-03-25 409: }
eebfe1f40f 2020-03-25 410: }
eebfe1f40f 2020-03-25 411:
eebfe1f40f 2020-03-25 412: #undef parse_xvfs_minirivet_getbyte
eebfe1f40f 2020-03-25 413:
eebfe1f40f 2020-03-25 414: return(1);
eebfe1f40f 2020-03-25 415: }
eebfe1f40f 2020-03-25 416:
160dcdcda4 2020-04-03 417: static int xvfs_create(FILE *outfp, const struct xvfs_options * const options) {
eebfe1f40f 2020-03-25 418: const int template_len = 65536;
eebfe1f40f 2020-03-25 419: const char * const template_file = "lib/xvfs/xvfs.c.rvt";
eebfe1f40f 2020-03-25 420: FILE *fp;
eebfe1f40f 2020-03-25 421: char *template, *template_p;
eebfe1f40f 2020-03-25 422: int template_remain;
eebfe1f40f 2020-03-25 423: size_t fread_ret;
eebfe1f40f 2020-03-25 424: int retval;
eebfe1f40f 2020-03-25 425:
eebfe1f40f 2020-03-25 426: fp = fopen(template_file, "r");
eebfe1f40f 2020-03-25 427: if (!fp) {
eebfe1f40f 2020-03-25 428: return(0);
eebfe1f40f 2020-03-25 429: }
eebfe1f40f 2020-03-25 430:
eebfe1f40f 2020-03-25 431: template = malloc(template_len);
eebfe1f40f 2020-03-25 432: template_remain = template_len;
eebfe1f40f 2020-03-25 433: if (!template) {
eebfe1f40f 2020-03-25 434: fclose(fp);
eebfe1f40f 2020-03-25 435:
eebfe1f40f 2020-03-25 436: return(0);
eebfe1f40f 2020-03-25 437: }
eebfe1f40f 2020-03-25 438:
eebfe1f40f 2020-03-25 439: template_p = template;
eebfe1f40f 2020-03-25 440: while (1) {
eebfe1f40f 2020-03-25 441: fread_ret = fread(template_p, 1, template_remain, fp);
eebfe1f40f 2020-03-25 442: if (fread_ret <= 0) {
eebfe1f40f 2020-03-25 443: break;
eebfe1f40f 2020-03-25 444: }
eebfe1f40f 2020-03-25 445:
eebfe1f40f 2020-03-25 446: template_p += fread_ret;
eebfe1f40f 2020-03-25 447: template_remain -= fread_ret;
eebfe1f40f 2020-03-25 448: }
eebfe1f40f 2020-03-25 449: if (template_remain > 0) {
eebfe1f40f 2020-03-25 450: *template_p = '\0';
eebfe1f40f 2020-03-25 451: }
eebfe1f40f 2020-03-25 452:
eebfe1f40f 2020-03-25 453: fclose(fp);
eebfe1f40f 2020-03-25 454:
eebfe1f40f 2020-03-25 455: retval = parse_xvfs_minirivet(outfp, template, options);
eebfe1f40f 2020-03-25 456:
eebfe1f40f 2020-03-25 457: free(template);
eebfe1f40f 2020-03-25 458:
eebfe1f40f 2020-03-25 459: return(retval);
eebfe1f40f 2020-03-25 460: }
eebfe1f40f 2020-03-25 461:
eebfe1f40f 2020-03-25 462: /*
eebfe1f40f 2020-03-25 463: * Parse command line options
eebfe1f40f 2020-03-25 464: */
160dcdcda4 2020-04-03 465: static int parse_options(int argc, char **argv, struct xvfs_options *options) {
eebfe1f40f 2020-03-25 466: char *arg;
eebfe1f40f 2020-03-25 467: char **option;
eebfe1f40f 2020-03-25 468: int idx;
eebfe1f40f 2020-03-25 469: int retval;
eebfe1f40f 2020-03-25 470:
eebfe1f40f 2020-03-25 471: for (idx = 0; idx < argc; idx++) {
eebfe1f40f 2020-03-25 472: arg = argv[idx];
eebfe1f40f 2020-03-25 473:
eebfe1f40f 2020-03-25 474: if (strcmp(arg, "--directory") == 0) {
eebfe1f40f 2020-03-25 475: option = &options->directory;
eebfe1f40f 2020-03-25 476: } else if (strcmp(arg, "--name") == 0) {
eebfe1f40f 2020-03-25 477: option = &options->name;
eebfe1f40f 2020-03-25 478: } else {
eebfe1f40f 2020-03-25 479: fprintf(stderr, "Invalid argument %s\n", arg);
eebfe1f40f 2020-03-25 480:
eebfe1f40f 2020-03-25 481: return(0);
eebfe1f40f 2020-03-25 482: }
eebfe1f40f 2020-03-25 483:
eebfe1f40f 2020-03-25 484: idx++;
eebfe1f40f 2020-03-25 485: arg = argv[idx];
eebfe1f40f 2020-03-25 486: *option = arg;
eebfe1f40f 2020-03-25 487: }
eebfe1f40f 2020-03-25 488:
eebfe1f40f 2020-03-25 489: retval = 1;
eebfe1f40f 2020-03-25 490: if (!options->directory) {
eebfe1f40f 2020-03-25 491: fprintf(stderr, "error: --directory must be specified\n");
eebfe1f40f 2020-03-25 492: retval = 0;
eebfe1f40f 2020-03-25 493: }
eebfe1f40f 2020-03-25 494:
eebfe1f40f 2020-03-25 495: if (!options->name) {
eebfe1f40f 2020-03-25 496: fprintf(stderr, "error: --name must be specified\n");
eebfe1f40f 2020-03-25 497: retval = 0;
eebfe1f40f 2020-03-25 498: }
eebfe1f40f 2020-03-25 499:
eebfe1f40f 2020-03-25 500: return(retval);
eebfe1f40f 2020-03-25 501: }
eebfe1f40f 2020-03-25 502:
eebfe1f40f 2020-03-25 503: int main(int argc, char **argv) {
160dcdcda4 2020-04-03 504: struct xvfs_options options = {0};
eebfe1f40f 2020-03-25 505: int parse_options_ret, xvfs_create_ret;
eebfe1f40f 2020-03-25 506:
eebfe1f40f 2020-03-25 507: argc--;
eebfe1f40f 2020-03-25 508: argv++;
eebfe1f40f 2020-03-25 509:
eebfe1f40f 2020-03-25 510: parse_options_ret = parse_options(argc, argv, &options);
eebfe1f40f 2020-03-25 511: if (!parse_options_ret) {
eebfe1f40f 2020-03-25 512: return(1);
eebfe1f40f 2020-03-25 513: }
eebfe1f40f 2020-03-25 514:
eebfe1f40f 2020-03-25 515: xvfs_create_ret = xvfs_create(stdout, &options);
eebfe1f40f 2020-03-25 516: if (!xvfs_create_ret) {
eebfe1f40f 2020-03-25 517: return(1);
eebfe1f40f 2020-03-25 518: }
eebfe1f40f 2020-03-25 519:
eebfe1f40f 2020-03-25 520: return(0);
eebfe1f40f 2020-03-25 521: }