void bind_names ( node_t *root ) { if (root == NULL) return; switch (root->type.index) { case FUNCTION_LIST: { add_functions_to_symtab ( root ); traverse_children ( root ); break; } case FUNCTION: { scope_add (); add_parameters_to_scope ( root ); if ( root->children[2]->type.index == BLOCK) { bind_names ( root->children[2]->children[0] ); bind_names ( root->children[2]->children[1] ); } else fprintf(stderr, "Expected BLOCK-statement after FUNCTION \"%s\"\n", (char *) root->data); scope_remove (); break; } case BLOCK: { scope_add (); traverse_children ( root ); scope_remove (); break; } case DECLARATION_LIST: { int stack_offset = -VSL_PTR_SIZE; for ( int i = 0; i < root->n_children; i++ ) { node_t *declaration_n = root->children[i]; stack_offset = add_variables_to_scope ( declaration_n, stack_offset ); } break; } case VARIABLE: { symbol_t *var = symbol_get ( (char *) root->data ); if ( var != NULL ) root->entry = var; else fprintf(stderr, "The variable \"%s\" is not declared.\n", (char *) root->data); traverse_children ( root ); break; } case TEXT: { add_text ( root ); traverse_children ( root ); break; } default: traverse_children ( root ); } }
/* Suggests children of the specified chunk. */ static void suggest_children(const key_chunk_t *chunk, const wchar_t prefix[], vle_keys_list_cb cb, int fold_subkeys) { const key_chunk_t *child; const size_t prefix_len = wcslen(prefix); wchar_t item[prefix_len + 1U + 1U]; wcscpy(item, prefix); item[prefix_len + 1U] = L'\0'; for(child = chunk->child; child != NULL; child = child->next) { if(!fold_subkeys || child->children_count <= 1) { traverse_children(child, prefix, &suggest_chunk, cb); } else { char msg[64]; snprintf(msg, sizeof(msg), "{ %d mappings folded }", (int)child->children_count); item[prefix_len] = child->key; cb(item, L"", msg); } } }
void vle_keys_list(int mode, vle_keys_list_cb cb, int user_only) { const key_chunk_t *user = &user_cmds_root[mode]; const key_chunk_t *builtin = &builtin_cmds_root[mode]; /* Don't traverse empty tries. */ if(user->children_count != 0U) { traverse_children(user, L"", &list_chunk, cb); /* Put separator only when it's needed. */ if(!user_only && builtin->children_count != 0U) { cb(L"", L"", ""); } } if(!user_only && builtin->children_count != 0U) { traverse_children(builtin, L"", &list_chunk, cb); } }
/* Visits every child of the tree and calls cb with param on it. */ static void traverse_children(const key_chunk_t *chunk, const wchar_t prefix[], traverse_func cb, void *param) { const key_chunk_t *child; const size_t prefix_len = wcslen(prefix); wchar_t item[prefix_len + 1U + 1U]; wcscpy(item, prefix); item[prefix_len] = chunk->key; item[prefix_len + 1U] = L'\0'; cb(chunk, item, param); for(child = chunk->child; child != NULL; child = child->next) { traverse_children(child, item, cb, param); } }
int main(int argc, char **argv) { int c; char *blkszptr; char **path_argv; char *default_dot_path[] = {".", NULL}; struct winsize win; FTS* ftsptr; FTSENT *argv_list; FTSENT *cur; FTSENT *read; int fts_options = FTS_PHYSICAL; int (* comp)(const FTSENT** obj1, const FTSENT** obj2); /* * get term width * refers to NetBSD's implementation */ if (isatty(STDOUT_FILENO)) { if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &win) == 0 &&win.ws_col > 0) { win_width = win.ws_col; } } comp = sortbyname; setprogname(argv[0]); /* some default setting */ if (isatty(STDOUT_FILENO)) { all_flags.qflag = 1; all_flags.Cflag = 1; } else { all_flags.wflag = 1; all_flags.oneflag = 1; } /*-A always set for super user*/ if (getuid() == 0) { all_flags.Aflag = 1; } while( (c = getopt(argc, argv, "AacdFfhiklnqRrSstuw1xC")) != -1 ) { switch(c) { case 'A': all_flags.Aflag = 1; break; case 'a': all_flags.aflag = 1; break; case 'd': all_flags.dflag = 1; break; case 'f': comp = NULL; all_flags.fflag = 1; break; case 'F': all_flags.Fflag = 1; break; case 'R': all_flags.Rflag = 1; break; case 'i': all_flags.iflag = 1; break; case 'l': //overwrite all_flags.nflag = 0; all_flags.oneflag = 0; all_flags.Cflag = 0; all_flags.xflag = 0; all_flags.lflag = 1; break; case 'n': //overwrite all_flags.lflag = 0; all_flags.oneflag = 0; all_flags.Cflag = 0; all_flags.xflag = 0; all_flags.nflag = 1; break; case 's': all_flags.sflag = 1; break; case 'S': comp = sortbysize; all_flags.Sflag = 1; break; case 'q': all_flags.wflag = 0; all_flags.qflag = 1; break; case 'w': all_flags.qflag = 0; all_flags.wflag = 1; break; case 't': comp = sortbytime; all_flags.tflag = 1; break; case '1': all_flags.lflag = 0; all_flags.nflag = 0; all_flags.oneflag = 1; break; case 'c': all_flags.uflag = 0; all_flags.cflag = 1; break; case 'x': //overwirte all_flags.oneflag = 0; all_flags.lflag = 0; all_flags.nflag = 0; all_flags.Cflag = 0; all_flags.xflag = 1; break; case 'C': //overwrite all_flags.oneflag = 0; all_flags.lflag = 0; all_flags.nflag = 0; all_flags.xflag = 0; all_flags.Cflag = 1; break; case 'u': all_flags.cflag = 0; all_flags.uflag = 1; break; case 'k': all_flags.hflag = 0; all_flags.kflag = 1; break; case 'h': all_flags.kflag = 0; all_flags.hflag = 1; break; case 'r': all_flags.rflag = 1; break; default: usage(); break; } } argc -= optind; argv += optind; cldlist_init(); path_argv = (argc == 0) ? default_dot_path : argv; /*set block size, blksize_t shall be signed integer*/ if ( (blkszptr = getenv("BLOCKSIZE")) != NULL ) { blocksize = atoi(blkszptr); } else { blocksize = DEFAULT_BLOCKSIZE; } if (all_flags.kflag) { divide_term = 1024; } if (all_flags.aflag) { fts_options = fts_options | FTS_SEEDOT; } if (all_flags.rflag) { if (all_flags.Sflag) { comp = sortbyrsize; } else if (all_flags.tflag) { comp = sortbyrsize; } else { comp = sortbyname; } } if ( (ftsptr = fts_open(path_argv, fts_options, comp)) == NULL) { if (errno != 0) { (void)fprintf(stderr, "%s: fts_open error %s\n", getprogname(), strerror(errno)); exit(EXIT_FAILURE); } } /*the special use case of fts_children, go through all files in the argv list*/ if ( (argv_list = fts_children(ftsptr, 0)) == NULL ) { if (errno != 0) { (void)fprintf(stderr, "%s: fts_open error %s\n", getprogname(), strerror(errno)); exit(EXIT_FAILURE); } } /* * refer to NetBSD implementation * here we handle all `non-directory` files and error, * leave the directory for the fts_read below */ for (cur = argv_list; cur != NULL; cur = cur->fts_link) { if (cur->fts_info == FTS_ERR || cur->fts_info == FTS_NS || cur->fts_info == FTS_DNR) { warnx("can't access %s: %s",cur->fts_name, strerror(cur->fts_errno)); /* * because error message also consider as an output * `outputnum++` will make the directory to output its path name */ outputnum++; continue; } if (!all_flags.dflag && cur->fts_info == FTS_D) { /*leave the directory to the fts_read below*/ outputnum++; continue; } outputentnum++; outputnum++; cook_entry(cur); } //Parent = NULL means it's at root level traverse_children(NULL); do{ if (all_flags.dflag) { break; } /* * handle the directory entry */ while( (read = fts_read(ftsptr)) != NULL) { unsigned short info = read->fts_info; if (info == FTS_DC) { warnx("%s causes a cycle in the tree ",read->fts_path); continue; } if (info == FTS_DNR || info == FTS_ERR) { warnx("can't access %s: %s",read->fts_path, strerror(read->fts_errno)); continue; } if (info == FTS_D) { FTSENT* childrenptr; childrenptr = fts_children(ftsptr,0); if (childrenptr == NULL && errno != 0) { /* * if error heppen we don't do anything this moment * error will be printed at the postorder visit */ continue; } config_output(childrenptr); // cook_multi_cols(); traverse_children(read); if (!all_flags.Rflag && childrenptr != NULL) { if (fts_set(ftsptr, read, FTS_SKIP) != 0) { (void)fprintf(stderr, "%s: fts_set error %s\n", getprogname(), strerror(errno)); exit(EXIT_FAILURE); } } } } }while(0); if (read == NULL && errno != 0) { (void)fprintf(stderr, "%s: fts_read error %s\n", getprogname(), strerror(errno)); exit(EXIT_FAILURE); } cldlist_clear(); return 0; }