str BOXopen(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) { str name; (void) cntxt; (void) mb; /*fool compiler */ name = *(str *) getArgReference(stk, pci, 1); if (openBox(name) != 0) return MAL_SUCCEED; throw(MAL, "box.open", BOX_CLOSED); }
int main(int argc, char** argv) { if (argc > 1 && !strcmp(argv[1], "-v")) { g_verbose = true; ++argv; --argc; } if (argc > 1 && !strcmp(argv[1], "-r")) { g_recursive = true; ++argv; --argc; } if (argc != 3) { fprintf(stderr, "Usage: treecat treeLocation boxcode\n"); exit(1); } char* boxcode = argv[2]; g_treeLocation = argv[1]; char fileboxcode[1000]; strcpy(fileboxcode, boxcode); FILE* fp = 0; int fileBoxLength; for (fileBoxLength = strlen(boxcode); fileBoxLength >= 0; --fileBoxLength) { fileboxcode[fileBoxLength] = '\0'; fp = openBox(fileboxcode); if (fp) break; } boxcode += fileBoxLength; char fullboxcode[1000]; strcpy(fullboxcode, fileboxcode); strcat(fullboxcode, boxcode); char buf[10000]; while (*boxcode && fgets(buf, sizeof(buf), fp)) { if (buf[0] != 'X') { *boxcode = '\0'; fprintf(stderr, "box = %s\n", argv[2]); fputs(buf, stdout); exit(0); } if (*boxcode == '1') processTree(fp, false, boxcode); ++boxcode; } processTree(fp, true, fullboxcode); }
void processTree(FILE* fp, bool print, char* boxcode) { int boxdepth = strlen(boxcode); char buf[10000]; int depth = 0; while (fgets(buf, sizeof(buf), fp)) { bool filledHole = false; if (g_recursive && print && buf[0] == 'H') { boxcode[boxdepth + depth] = '\0'; FILE* fpH = openBox(boxcode); if (fpH) { processTree(fpH, print, boxcode); fclose(fpH); filledHole = true; } else { fprintf(stderr, "missing %s\n", boxcode); } } if (print && !filledHole) fputs(buf, stdout); if (buf[0] == 'X') { boxcode[boxdepth + depth] = '0'; ++depth; } else { for (; depth > 0 && boxcode[boxdepth + depth-1] == '1'; --depth) { } if (depth > 0) { boxcode[boxdepth + depth-1] = '1'; } else { boxcode[boxdepth] = '\0'; return; } } } boxcode[boxdepth + depth] = '\0'; fprintf(stderr, "premature EOF at %s\n", boxcode); }
bool processTree(FILE* fp, FILE* out, bool printTree, bool printHoles, char* boxcode) { int boxdepth = strlen(boxcode); char buf[10000]; char fileName[10000]; int depth = 0; while (fgets(buf, sizeof(buf), fp)) { bool filledHole = false; // Open HOLE file if exists. If no printing is set, we don't need to traverse HOLEs if (g_recursive && buf[0] == 'H' && depth > 0) { bool nbd_var_box = (strchr(buf,'V') != NULL); FILE* fpH = openBox(boxcode, fileName); if (fpH) { FILE* outH = tmpfile(); if (outH) { bool success = processTree(fpH, outH, printTree, printHoles, boxcode); fclose(fpH); if (!success) { fclose(outH); // The tree is incomplete, so we rename the boxfile to mark as incomplete // TODO: Not sure if treecat should have the power to rename files if (g_mark_incomplete) if (!mark(fileName,".incomplete")) fprintf(stderr, "failed to mark %s as incomplete\n", fileName); } else { // If the HOLE subtree is complete, print it to the output stream rewind(outH); bool success = putStream(out,outH); fclose(outH); if (!success) { fprintf(stderr, "failed to print HOLE %s subtree\n", boxcode); break; } else { filledHole = true; } } } } if (printHoles && !filledHole && ! nbd_var_box) fprintf(out, "%s\n", boxcode); // Print the missing boxcode to stdout } if (printTree && !filledHole) { fputs(buf, out); // Print the buffer if we are printing out the filled tree } if (buf[0] == 'X') { boxcode[boxdepth + depth] = '0'; // Descend via left branch ++depth; boxcode[boxdepth + depth] = '\0'; } else { // Go up as many nodes as necessary for (; depth > 0 && boxcode[boxdepth + depth-1] == '1'; --depth) {} if (depth > 0) { boxcode[boxdepth + depth-1] = '1'; // Jump from left to right node boxcode[boxdepth + depth] = '\0'; // Truncate to keep box current } else { boxcode[boxdepth] = '\0'; // Truncate to keep box current return true; } } } // If we get to this point, the tree is incomplete // TODO: This may be unnecssary code as we rename incomplete trees if (printHoles) { // Print the box we "should" be at as missing fprintf(out, "%s\n", boxcode); // Print the missing boxcode to stdout // We list all other missing boxes for (int i = depth; i > 0; --i) { if (boxcode[boxdepth + i-1] != '1') { boxcode[boxdepth + i-1] = '1'; // Jump from left to right node boxcode[boxdepth + i] = '\0'; // Truncate to keep box current fprintf(out, "%s\n", boxcode); // Print the missing boxcode to stdout } else { boxcode[boxdepth + i] = '\0'; // Truncate to keep box current } } } return false; }
int main(int argc, char** argv) { bool printTree = true; bool printHoles = false; if (argc > 1 && strcmp(argv[1], "--holes") == 0) { printTree = false; printHoles = true; ++argv; --argc; } if (argc > 1 && strcmp(argv[1], "--mark") == 0) { g_mark_incomplete = true; ++argv; --argc; } if (argc > 1 && strcmp(argv[1], "-s") == 0) { printTree = false; printHoles = false; ++argv; --argc; } if (argc > 1 && strcmp(argv[1], "-v") == 0) { g_verbose = true; ++argv; --argc; } if (argc > 1 && strcmp(argv[1], "-r") == 0) { g_recursive = true; ++argv; --argc; } if (argc != 3) { fprintf(stderr, "Usage: treecat [--holes] [--mark] [-s] [-v] [-r] treeLocation boxcode\n"); fprintf(stderr, "holes : do not print the tree but print the holes\n"); fprintf(stderr, "mark : rename incomplete (sub)tree file(s) containing given boxcode (sub if -r)\n"); fprintf(stderr, "s : silent, don't print trees or holes\n"); fprintf(stderr, "v : verbose\n"); fprintf(stderr, "r : recur over all subtree files to prince full subtree of boxcode\n"); fprintf(stderr, "WARNING: If all --mark -r are set and boxcode is root or '', then mark any foreign tree files\n"); exit(1); } // The fullboxcode parameter can specify the fileName and sequetial boxcode // A boxcode is just a sequence of zeros and ones giving a posiiton in a binary tree depth-first traversal // The treeFile will also be in pre-order depth-first char fullboxcode[10000]; char fileboxcode[10000]; strncpy(fullboxcode, argv[2], 10000); strncpy(fileboxcode, argv[2], 10000); g_treeLocation = argv[1]; char fileName[10000]; int fileBoxLength = strlen(fullboxcode); if ((fileBoxLength == 0) || (strncmp(fullboxcode, "root", fileBoxLength) == 0)) { g_start_is_root = true; } // TODO: Taging of foreign files may be dangerous if (g_start_is_root && g_mark_incomplete && g_recursive) { DIR * dirp = opendir(g_treeLocation); struct dirent * dp; while ((dp = readdir(dirp)) != NULL) { if (ends_with(dp->d_name,"out")) { sprintf(fileName, "%s/%s", g_treeLocation, dp->d_name); unopened_out_files.push_back(std::string(fileName)); } } } // See if a file with the tree for a prefix of the box exists FILE* fp = 0; while (fileBoxLength >= 0) { fileboxcode[fileBoxLength] = '\0'; fp = openBox(fileboxcode, fileName); if (fp) { break; } --fileBoxLength; } if (!fp) exit(1); char * boxcode_const = (char *)calloc(10000, sizeof(char)); strncpy(boxcode_const, fullboxcode+fileBoxLength, 10000); char * boxcode = boxcode_const; char buf[10000]; // If the boxcode is still not empty, we traverse down the tree and print only // once we get to the proper node. We terminate early if the node does not exist while (*boxcode && fgets(buf, sizeof(buf), fp)) { if (buf[0] != 'X') { // If not a splitting, print the test failed by the truncated box *boxcode = '\0'; fprintf(stderr, "terminal box = %s%s\n", fileboxcode, boxcode_const); if (printTree) fputs(buf, stdout); free(boxcode_const); fclose(fp); exit(0); } if (*boxcode == '1') { // Actually have to process the tree if we go right at any point in the boxcode int success = processTree(fp, NULL, false, false, boxcode); if (!success) exit(1); // Incomplete tree or boxcode not found } ++boxcode; // Keeps going left in the tree as *boxcode == 0 } free(boxcode_const); FILE* out = tmpfile(); if (!out) exit(1); bool success = processTree(fp, out, printTree, printHoles, fullboxcode); fclose(fp); if (g_start_is_root && g_mark_incomplete && g_recursive) { for (std::vector<std::string>::iterator it = unopened_out_files.begin() ; it != unopened_out_files.end(); ++it) { fprintf(stderr, "unopened/foreign out file = %s\n", it->c_str()); // TODO: Not sure if treecat should have the power to rename files if (!mark(it->c_str(),".foreign")) fprintf(stderr, "failed to mark %s as foreign\n", it->c_str()); } } if (!success) { fclose(out); // The tree is incomplete, so we rename the boxfile to mark as incomplete // TODO: Not sure if treecat should have the power to rename files if (g_mark_incomplete) { if (!mark(fileName,".incomplete")) fprintf(stderr, "failed to mark %s as incomplete\n", fileName); } exit(1); } else { rewind(out); bool putSuccess = putStream(stdout, out); fclose(out); if (!putSuccess) exit(1); else exit(0); } }