int parse_options_subcommand(int argc, const char **argv, const struct option *options, const char *const subcommands[], const char *usagestr[], int flags) { struct parse_opt_ctx_t ctx; /* build usage string if it's not provided */ if (subcommands && !usagestr[0]) { char *buf = NULL; astrcatf(&buf, "%s %s [<options>] {", subcmd_config.exec_name, argv[0]); for (int i = 0; subcommands[i]; i++) { if (i) astrcat(&buf, "|"); astrcat(&buf, subcommands[i]); } astrcat(&buf, "}"); usagestr[0] = buf; } parse_options_start(&ctx, argc, argv, flags); switch (parse_options_step(&ctx, options, usagestr)) { case PARSE_OPT_HELP: exit(129); case PARSE_OPT_DONE: break; case PARSE_OPT_LIST_OPTS: while (options->type != OPTION_END) { if (options->long_name) printf("--%s ", options->long_name); options++; } putchar('\n'); exit(130); case PARSE_OPT_LIST_SUBCMDS: if (subcommands) { for (int i = 0; subcommands[i]; i++) printf("%s ", subcommands[i]); } putchar('\n'); exit(130); default: /* PARSE_OPT_UNKNOWN */ if (ctx.argv[0][1] == '-') astrcatf(&error_buf, "unknown option `%s'", ctx.argv[0] + 2); else astrcatf(&error_buf, "unknown switch `%c'", *ctx.opt); usage_with_options(usagestr, options); } return parse_options_end(&ctx); }
/** ************************************************************************** * \brief Recursively convert a node to its XSPF representation *****************************************************************************/ static int nodeToXSPF( char **pp_buffer, node *n, bool b_root ) { if( !b_root ) { if( astrcatf( pp_buffer, " <vlc:node title=\"%s\">\n", n->name ) < 0 ) return -1; } if( n->child ) nodeToXSPF( pp_buffer, n->child, false ); item *i = n->media; while( i ) { if( astrcatf( pp_buffer, " <vlc:item tid=\"%d\" />\n", i->id ) < 0 ) return -1; i = i->next; } if( !b_root ) { if( astrcatf( pp_buffer, " </vlc:node>\n" ) < 0 ) return -1; } return VLC_SUCCESS; }
static void list_commands_in_dir(struct cmdnames *cmds, const char *path, const char *prefix) { int prefix_len; DIR *dir = opendir(path); struct dirent *de; char *buf = NULL; if (!dir) return; if (!prefix) prefix = "perf-"; prefix_len = strlen(prefix); astrcatf(&buf, "%s/", path); while ((de = readdir(dir)) != NULL) { int entlen; if (!strstarts(de->d_name, prefix)) continue; astrcat(&buf, de->d_name); if (!is_executable(buf)) continue; entlen = strlen(de->d_name) - prefix_len; if (has_extension(de->d_name, ".exe")) entlen -= 4; add_cmdname(cmds, de->d_name + prefix_len, entlen); } closedir(dir); free(buf); }
/** ************************************************************************** * \brief Write the XSPF playlist given the list of files *****************************************************************************/ static int WriteXSPF( char **pp_buffer, vlc_array_t *p_filenames, const char *psz_zippath ) { char *psz_zip = strrchr( psz_zippath, DIR_SEP_CHAR ); psz_zip = vlc_xml_encode( psz_zip ? (psz_zip+1) : psz_zippath ); if( asprintf( pp_buffer, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" "<playlist version=\"1\" xmlns=\"http://xspf.org/ns/0/\" " "xmlns:vlc=\"http://www.videolan.org/vlc/playlist/ns/0/\">\n" " <title>%s</title>\n" " <trackList>\n", psz_zip ) == -1) return -1; /* Root node */ node *playlist = new_node( psz_zip ); free( psz_zip ); /* Encode the URI and append ZIP_SEP */ char *psz_pathtozip; escapeToXml( &psz_pathtozip, psz_zippath ); if( astrcatf( &psz_pathtozip, "%s", ZIP_SEP ) < 0 ) { free_all_node( playlist ); return -1; } int i_track = 0; for( int i = 0; i < vlc_array_count( p_filenames ); ++i ) { char *psz_name = (char*) vlc_array_item_at_index( p_filenames, i ); int i_len = strlen( psz_name ); if( !i_len ) continue; /* Is it a folder ? */ if( psz_name[i_len-1] == '/' ) { /* Do nothing */ } else /* File */ { /* Extract file name */ char *psz_file = strrchr( psz_name, '/' ); psz_file = vlc_xml_encode( psz_file ? (psz_file+1) : psz_name ); /* Build full MRL */ char *psz_path = strdup( psz_pathtozip ); char *psz_escapedName; escapeToXml( &psz_escapedName, psz_name ); if( astrcatf( &psz_path, "%s", psz_escapedName ) < 0 ) { free( psz_escapedName ); return -1; } free( psz_escapedName ); /* Track information */ if( astrcatf( pp_buffer, " <track>\n" " <location>zip://%s</location>\n" " <title>%s</title>\n" " <extension application=\"http://www.videolan.org/vlc/playlist/0\">\n" " <vlc:id>%d</vlc:id>\n" " </extension>\n" " </track>\n", psz_path, psz_file, i_track ) < 0 ) return -1; free( psz_file ); free( psz_path ); /* Find the parent node */ node *parent = findOrCreateParentNode( playlist, psz_name ); assert( parent ); /* Add the item to this node */ item *tmp = parent->media; if( !tmp ) { parent->media = new_item( i_track ); } else { while( tmp->next ) { tmp = tmp->next; } tmp->next = new_item( i_track ); } ++i_track; } } free( psz_pathtozip ); /* Close tracklist, open the extension */ if( astrcatf( pp_buffer, " </trackList>\n" " <extension application=\"http://www.videolan.org/vlc/playlist/0\">\n" ) < 0 ) return -1; /* Write the tree */ if( nodeToXSPF( pp_buffer, playlist, true ) < 0 ) return -1; /* Close extension and playlist */ if( astrcatf( pp_buffer, " </extension>\n</playlist>\n" ) < 0 ) return -1; /* printf( "%s", *pp_buffer ); */ free_all_node( playlist ); return VLC_SUCCESS; }