bool GameStateConfigBase::parseKeyButtons(FileParser &infile) { // @CLASS GameStateConfigBase|Description of menus/config.txt if (infile.key == "button_ok") { // @ATTR button_ok|int, int, alignment : X, Y, Alignment|Position of the "OK" button. int x = popFirstInt(infile.val); int y = popFirstInt(infile.val); ALIGNMENT a = parse_alignment(popFirstString(infile.val)); ok_button->setBasePos(x, y, a); } else if (infile.key == "button_defaults") { // @ATTR button_defaults|int, int, alignment : X, Y, Alignment|Position of the "Defaults" button. int x = popFirstInt(infile.val); int y = popFirstInt(infile.val); ALIGNMENT a = parse_alignment(popFirstString(infile.val)); defaults_button->setBasePos(x, y, a); } else if (infile.key == "button_cancel") { // @ATTR button_cancel|int, int, alignment : X, Y, Alignment|Position of the "Cancel" button. int x = popFirstInt(infile.val); int y = popFirstInt(infile.val); ALIGNMENT a = parse_alignment(popFirstString(infile.val)); cancel_button->setBasePos(x, y, a); } else { return false; } return true; }
void GameSwitcher::loadFPS() { // Load FPS rendering settings FileParser infile; // @CLASS GameSwitcher: FPS counter|Description of menus/fps.txt if (infile.open("menus/fps.txt")) { while(infile.next()) { // @ATTR position|x (integer), y (integer), align (alignment)|Position of the fps counter. if(infile.key == "position") { fps_position.x = popFirstInt(infile.val); fps_position.y = popFirstInt(infile.val); fps_corner = parse_alignment(popFirstString(infile.val)); } // @ATTR color|r (integer), g (integer), b (integer)|Color of the fps counter text. else if(infile.key == "color") { fps_color = toRGB(infile.val); } else { infile.error("GameSwitcher: '%s' is not a valid key.", infile.key.c_str()); } } infile.close(); } // this is a dummy string used to approximate the fps position when aligned to the right font->setFont("font_regular"); fps_position.w = font->calc_width("00 fps"); fps_position.h = font->getLineHeight(); // Delete the label object if it exists (we'll recreate this with showFPS()) if (label_fps) { delete label_fps; label_fps = NULL; } }
Subtitles::Subtitles() : current_id(-1) , visible(false) , background(NULL) , background_color(0,0,0,200) , visible_ticks(0) { FileParser infile; // @CLASS Subtitles|Description of soundfx/subtitles.txt if (infile.open("soundfx/subtitles.txt")) { while (infile.next()) { if (infile.new_section && infile.section == "subtitle") { filename.resize(filename.size()+1); text.resize(text.size()+1); } else if (infile.section == "style") { if (infile.key == "text_pos") { // @ATTR style.text_pos|label|Position and style of the subtitle text. text_pos = eatLabelInfo(infile.val); } else if (infile.key == "pos") { // @ATTR style.pos|point|Position of the subtitle text relative to alignment. label_pos = toPoint(infile.val); } else if (infile.key == "align") { // @ATTR style.align|alignment|Alignment of the subtitle text. label_alignment = parse_alignment(infile.val); } else if (infile.key == "background_color") { // @ATTR style.background_color|color, int : Color, Alpha|Color and alpha of the subtitle background rectangle. background_color = toRGBA(infile.val); } } if (filename.empty() || text.empty()) continue; if (infile.key == "id") { // @ATTR subtitle.id|filename|Filename of the sound file that will trigger this subtitle. std::locale loc; const std::collate<char>& coll = std::use_facet<std::collate<char> >(loc); const std::string realfilename = mods->locate(infile.val); unsigned long sid = coll.hash(realfilename.data(), realfilename.data()+realfilename.length()); filename.back() = sid; } else if (infile.key == "text") { // @ATTR subtitle.text|string|The subtitle text that will be displayed. text.back() = msg->get(infile.val); } } } assert(filename.size() == text.size()); }
GameStateLoad::GameStateLoad() : GameState() , background(NULL) , selection(NULL) , portrait_border(NULL) , portrait(NULL) , loading_requested(false) , loading(false) , loaded(false) , delete_items(true) , selected_slot(-1) , visible_slots(0) , scroll_offset(0) , has_scroll_bar(false) , game_slot_max(4) , text_trim_boundary(0) { if (items == NULL) items = new ItemManager(); label_loading = new WidgetLabel(); // Confirmation box to confirm deleting confirm = new MenuConfirm(msg->get("Delete Save"), msg->get("Delete this save?")); button_exit = new WidgetButton(); button_exit->label = msg->get("Exit to Title"); button_new = new WidgetButton(); button_new->label = msg->get("New Game"); button_new->enabled = true; button_load = new WidgetButton(); button_load->label = msg->get("Choose a Slot"); button_load->enabled = false; button_delete = new WidgetButton(); button_delete->label = msg->get("Delete Save"); button_delete->enabled = false; scrollbar = new WidgetScrollBar(); // Set up tab list tablist = TabList(HORIZONTAL); tablist.add(button_exit); tablist.add(button_new); // Read positions from config file FileParser infile; // @CLASS GameStateLoad|Description of menus/gameload.txt if (infile.open("menus/gameload.txt")) { while (infile.next()) { // @ATTR button_new|int, int, alignment : X, Y, Alignment|Position of the "New Game" button. if (infile.key == "button_new") { int x = popFirstInt(infile.val); int y = popFirstInt(infile.val); ALIGNMENT a = parse_alignment(popFirstString(infile.val)); button_new->setBasePos(x, y, a); } // @ATTR button_load|int, int, alignment : X, Y, Alignment|Position of the "Load Game" button. else if (infile.key == "button_load") { int x = popFirstInt(infile.val); int y = popFirstInt(infile.val); ALIGNMENT a = parse_alignment(popFirstString(infile.val)); button_load->setBasePos(x, y, a); } // @ATTR button_delete|int, int, alignment : X, Y, Alignment|Position of the "Delete Save" button. else if (infile.key == "button_delete") { int x = popFirstInt(infile.val); int y = popFirstInt(infile.val); ALIGNMENT a = parse_alignment(popFirstString(infile.val)); button_delete->setBasePos(x, y, a); } // @ATTR button_exit|int, int, alignment : X, Y, Alignment|Position of the "Exit to Title" button. else if (infile.key == "button_exit") { int x = popFirstInt(infile.val); int y = popFirstInt(infile.val); ALIGNMENT a = parse_alignment(popFirstString(infile.val)); button_exit->setBasePos(x, y, a); } // @ATTR portrait|rectangle|Position and dimensions of the portrait image. else if (infile.key == "portrait") { portrait_dest = toRect(infile.val); } // @ATTR gameslot|rectangle|Position and dimensions of the first game slot. else if (infile.key == "gameslot") { gameslot_pos = toRect(infile.val); } // @ATTR name|label|The label for the hero's name. Position is relative to game slot position. else if (infile.key == "name") { name_pos = eatLabelInfo(infile.val); } // @ATTR level|label|The label for the hero's level. Position is relative to game slot position. else if (infile.key == "level") { level_pos = eatLabelInfo(infile.val); } // @ATTR class|label|The label for the hero's class. Position is relative to game slot position. else if (infile.key == "class") { class_pos = eatLabelInfo(infile.val); } // @ATTR map|label|The label for the hero's current location. Position is relative to game slot position. else if (infile.key == "map") { map_pos = eatLabelInfo(infile.val); } // @ATTR slot_number|label|The label for the save slot index. Position is relative to game slot position. else if (infile.key == "slot_number") { slot_number_pos = eatLabelInfo(infile.val); } // @ATTR loading_label|label|The label for the "Entering game world..."/"Loading saved game..." text. else if (infile.key == "loading_label") { loading_pos = eatLabelInfo(infile.val); } // @ATTR sprite|point|Position for the avatar preview image in each slot else if (infile.key == "sprite") { sprites_pos = toPoint(infile.val); } // @ATTR visible_slots|int|The maximum numbers of visible save slots. else if (infile.key == "visible_slots") { game_slot_max = toInt(infile.val); // can't have less than 1 game slot visible game_slot_max = std::max(game_slot_max, 1); } // @ATTR text_trim_boundary|int|The position of the right-side boundary where text will be shortened with an ellipsis. Position is relative to game slot position. else if (infile.key == "text_trim_boundary") { text_trim_boundary = toInt(infile.val); } else { infile.error("GameStateLoad: '%s' is not a valid key.", infile.key.c_str()); } } infile.close(); } // prevent text from overflowing on the right edge of game slots if (text_trim_boundary == 0 || text_trim_boundary > gameslot_pos.w) text_trim_boundary = gameslot_pos.w; button_new->refresh(); button_load->refresh(); button_delete->refresh(); loadGraphics(); readGameSlots(); color_normal = font->getColor("menu_normal"); refreshWidgets(); updateButtons(); // if we specified a slot to load at launch, load it now if (!LOAD_SLOT.empty()) { size_t load_slot_id = toInt(LOAD_SLOT) - 1; LOAD_SLOT.clear(); if (load_slot_id < game_slots.size()) { setSelectedSlot(static_cast<int>(load_slot_id)); loading_requested = true; } } render_device->setBackgroundColor(Color(0,0,0,0)); }
int main(int argc, char **argv) { //static const char OPTIONS[] = "hvlpsjPr:g:f::A:Ww:m:d:e:b:T:t:o:a:c:O:i:"; static const char OPTIONS[] = "A:a:b:c:D:d:E:e:F:f:g:hi:jlm:no:O:Ppr:sT:t:vWw:x:y:"; __sighandler_t sigint_original; char * const *file_names = NULL; size_t n_files = 0; int dither_mode = 0; int keep_power_on = 0; const char *waveform_id_str = "2"; int waveform_id = 2; int do_enumerate_waveforms = 0; int do_log_info = 0; int do_wait_power_off = 0; int do_synchro = 0; int do_infinite_loop = 0; int cfa = -1; int display_enable = 0; int do_fill = 0; int fill_color = 0xFF; int do_auto_rotate = 0; int rotation_angle = -1; int do_partial_update = 0; int use_manual_temperature = 0; int manual_temperature = 25; unsigned long pause_ms = 2000; const char *mode = NULL; const char *fbdev = NULL; const char *epdev = NULL; const char *background = NULL; struct plep_point offset = { 0, 0 }; enum epdoc_align_h align_h = EPDOC_ALIGN_H_NONE; enum epdoc_align_v align_v = EPDOC_ALIGN_V_NONE; struct plep_rect crop = { { 0, 0 }, { INT_MAX, INT_MAX } }; const char *doc_type = NULL; const char *conf_file = NULL; struct plep *plep; struct pldraw *pldraw; int onoff = -1; int c; int ret; int use_alternative_vsource = 0; while ((c = getopt(argc, argv, OPTIONS)) != -1) { switch (c) { case 'A': if (!strcmp(optarg, "l")) { use_alternative_vsource = 1; }else if (!strcmp(optarg, "h")) { use_alternative_vsource = 2; }else if (!strcmp(optarg, "lh")) { use_alternative_vsource = 3; }else if (!strcmp(optarg, "hl")) { use_alternative_vsource = 3; }else{ LOG("invalid alternative VSOURCE selection"); print_usage(); exit(EXIT_FAILURE); } break; case 'h': print_usage(); exit(EXIT_SUCCESS); break; case 'v': printf("%s v%s - %s\n%s\n%s\n", APP_NAME, VERSION, DESCRIPTION, COPYRIGHT, LICENSE); exit(EXIT_SUCCESS); break; case 'l': do_log_info = 1; break; case 'P': do_partial_update = 1; break; case 'p': do_wait_power_off = 1; break; case 's': do_synchro = 1; break; case 'j': do_infinite_loop = 1; break; case 'r': if (!strcmp(optarg, "auto")) { do_auto_rotate = 1; } else { unsigned long raw_angle; if (str2ul(optarg, &raw_angle) < 0) { LOG("failed to parse rotation angle"); print_usage(); exit(EXIT_FAILURE); } if ((raw_angle > 270) || (raw_angle % 90)) { LOG("invalid rotation angle"); print_usage(); exit(EXIT_FAILURE); } rotation_angle = raw_angle; } break; case 'g': if (str2ul(optarg, &pause_ms) < 0) { LOG("failed to parse pause duration"); print_usage(); exit(EXIT_FAILURE); } break; case 'f': if (optarg == NULL) { cfa = PLDRAW_CFA_GR_BW; } else { cfa = pldraw_get_cfa_id(optarg); if (cfa < 0) { LOG("Invalid CFA identifier: %s", optarg); print_usage(); exit(EXIT_FAILURE); } } break; case 'F':{ char* str = optarg; if (optarg == NULL) { // set color to white (0xFF) do_fill = 1; } else { do_fill = 1; if(!strncmp(optarg, "0x", 2) || !strncmp(optarg, "0X", 2)){ fill_color = strtoul(optarg, NULL, 16); }else{ fill_color = atoi(optarg); } } break; } case 'T': manual_temperature = atoi(optarg); use_manual_temperature = 1; break; case 'W': do_enumerate_waveforms = 1; break; case 'i': waveform_id_str = NULL; waveform_id = atoi(optarg); break; case 'w': waveform_id_str = optarg; break; case 'm': mode = optarg; break; case 'd': fbdev = optarg; break; case 'e': epdev = optarg; break; case 'b': background = optarg; break; case 't': doc_type = optarg; break; case 'o': if (parse_offset(&offset, optarg) < 0) { print_usage(); exit(EXIT_FAILURE); } break; case 'a': if (parse_alignment(&align_h, &align_v, optarg) < 0) { print_usage(); exit(EXIT_FAILURE); } break; case 'c': if (parse_crop(&crop, optarg) < 0) { print_usage(); exit(EXIT_FAILURE); } break; case 'O': conf_file = optarg; if (access(conf_file, F_OK)) { LOG_ERRNO("Configuration file"); exit(EXIT_FAILURE); } break; case 'x':{ onoff = atoi(optarg); break; } case 'E':{ //Enable Display N display_enable = atoi(optarg); if(display_enable > 3){ LOG("Invalid arguments"); exit(EXIT_FAILURE); } break; } case 'D':{ //disable Display N display_enable -= atoi(optarg); if(display_enable < -3){ LOG("Invalid arguments"); exit(EXIT_FAILURE); } break; } case 'y': dither_mode = atoi(optarg); LOG("dither_mode %i", dither_mode); if(display_enable < 0 || display_enable > 3){ LOG("Invalid arguments"); exit(EXIT_FAILURE); } break; case 'n':{ keep_power_on = 1; break; } case '?': default: LOG("Invalid arguments"); print_usage(); exit(EXIT_FAILURE); break; } } if (optind < argc) { file_names = &argv[optind]; n_files = argc - optind; } LOG("%s v%s", APP_NAME, VERSION); plep = plep_init(epdev, mode, conf_file); if (plep == NULL) { LOG("failed to initialise ePDC"); goto error_plep; } pldraw = pldraw_init(fbdev, conf_file); if (pldraw == NULL) { LOG("failed to initialise pldraw"); goto error_pldraw; } pldraw_set_plep(pldraw, plep); if(waveform_id_str){ waveform_id = plep_get_wfid(plep, waveform_id_str); if (waveform_id < 0) { LOG("Invalid waveform path: %s", waveform_id_str); goto error_pldraw; } } if (cfa >= 0) pldraw_set_cfa(pldraw, cfa); else cfa = pldraw_get_cfa(pldraw); if (cfa != PLDRAW_CFA_NONE) LOG("CFA: %s", pldraw_cfa_name[cfa]); if (rotation_angle < 0) rotation_angle = pldraw_get_rotation(pldraw); if (rotation_angle) LOG("rotation: %d", rotation_angle); if (do_log_info) pldraw_log_info(pldraw); sigint_original = signal(SIGINT, sigint_abort); if(onoff != -1){ LOG("POWER ONOFF:%i\n", onoff); if(onoff) plep_powerup(plep); else plep_powerdown(plep); exit(EXIT_SUCCESS); } if(display_enable != 0){ //LOG("DISPLAY ENABLE:%i\n", display_enable); if(display_enable>0){ plep_enable_display(plep, display_enable); }else{ plep_disable_display(plep, display_enable); } exit(EXIT_SUCCESS); } if (do_enumerate_waveforms) { ret = enumerate_waveforms(plep); } else { struct epdoc_opt opt; plep_set_opt(plep, PLEP_SYNC_UPDATE, do_synchro); if (do_wait_power_off) plep_set_opt(plep, PLEP_WAIT_POWER_OFF, 1); if(do_partial_update){ plep_set_opt(plep, PLEP_PARTIAL, 1); } if(use_manual_temperature){ plep_set_opt(plep, PLEP_TEMPERATURE, 1); plep_set_hw_opt(plep, PLEP_TEMPERATURE, manual_temperature); }else{ plep_set_opt(plep, PLEP_TEMPERATURE_AUTO, 1); } opt.dither_mode = dither_mode; opt.keep_power_on = keep_power_on; opt.do_auto_rotate = do_auto_rotate; opt.rotation_angle = rotation_angle; opt.wfid = waveform_id; opt.offset.x = offset.x; opt.offset.y = offset.y; opt.align_h = align_h; opt.align_v = align_v; memcpy(&opt.crop, &crop, sizeof opt.crop); opt.doc_type = doc_type; opt.use_alternative_vsource = use_alternative_vsource; if(do_fill){ pldraw_fill_rect(pldraw, pldraw_get_grey(pldraw, fill_color), &crop); plep_update_screen(plep, opt.wfid); }else{ ret = show_contents(pldraw, file_names, n_files, &opt, pause_ms, do_infinite_loop, background); } } signal(SIGINT, sigint_original); pldraw_free(pldraw); plep_free(plep); exit((ret < 0) ? EXIT_FAILURE : EXIT_SUCCESS); error_pldraw: plep_free(plep); error_plep: exit(EXIT_FAILURE); }
int batch_decoder_run(batch_decoder_t *bd) { int32 ctloffset, ctlcount, ctlincr; lineiter_t *li, *ali = NULL; search_run(bd->fwdtree); search_run(bd->fwdflat); ctloffset = cmd_ln_int32_r(bd->config, "-ctloffset"); ctlcount = cmd_ln_int32_r(bd->config, "-ctlcount"); ctlincr = cmd_ln_int32_r(bd->config, "-ctlincr"); if (bd->alignfh) ali = lineiter_start(bd->alignfh); for (li = lineiter_start(bd->ctlfh); li; li = lineiter_next(li)) { alignment_t *al = NULL; char *wptr[4]; int32 nf, sf, ef; if (li->lineno < ctloffset) { if (ali) ali = lineiter_next(ali); continue; } if ((li->lineno - ctloffset) % ctlincr != 0) { if (ali) ali = lineiter_next(ali); continue; } if (ctlcount != -1 && li->lineno >= ctloffset + ctlcount) break; if (ali) al = parse_alignment(ali->buf, search_factory_d2p(bd->sf)); sf = 0; ef = -1; nf = str2words(li->buf, wptr, 4); if (nf == 0) { /* Do nothing. */ } else if (nf < 0) { E_ERROR("Unexpected extra data in control file at line %d\n", li->lineno); } else { char *file, *uttid; file = wptr[0]; uttid = NULL; if (nf > 1) sf = atoi(wptr[1]); if (nf > 2) ef = atoi(wptr[2]); if (nf > 3) uttid = wptr[3]; /* Do actual decoding. */ batch_decoder_decode(bd, file, uttid, sf, ef, al); } alignment_free(al); if (ali) ali = lineiter_next(ali); } featbuf_producer_shutdown(search_factory_featbuf(bd->sf)); return 0; }
int main(int argc, char **argv) { static const char OPTIONS[] = "hvlpsjr:g:f::Ww:m:d:e:b:t:o:a:c:O:"; __sighandler_t sigint_original; char * const *file_names = NULL; size_t n_files = 0; const char *waveform_id_str = NULL; int waveform_id; int do_enumerate_waveforms = 0; int do_log_info = 0; int do_wait_power_off = 0; int do_synchro = 0; int do_infinite_loop = 0; int cfa = -1; int do_auto_rotate = 0; int rotation_angle = -1; unsigned long pause_ms = 2000; const char *mode = NULL; const char *fbdev = NULL; const char *epdev = NULL; const char *background = NULL; struct plep_point offset = { 0, 0 }; enum epdoc_align_h align_h = EPDOC_ALIGN_H_NONE; enum epdoc_align_v align_v = EPDOC_ALIGN_V_NONE; struct plep_rect crop = { { 0, 0 }, { INT_MAX, INT_MAX } }; const char *doc_type = NULL; const char *conf_file = NULL; struct plep *plep; struct pldraw *pldraw; int c; int ret; while ((c = getopt(argc, argv, OPTIONS)) != -1) { switch (c) { case 'h': print_usage(); exit(EXIT_SUCCESS); break; case 'v': printf("%s v%s - %s\n%s\n%s\n", APP_NAME, VERSION, DESCRIPTION, COPYRIGHT, LICENSE); exit(EXIT_SUCCESS); break; case 'l': do_log_info = 1; break; case 'p': do_wait_power_off = 1; break; case 's': do_synchro = 1; break; case 'j': do_infinite_loop = 1; break; case 'r': if (!strcmp(optarg, "auto")) { do_auto_rotate = 1; } else { unsigned long raw_angle; if (str2ul(optarg, &raw_angle) < 0) { LOG("failed to parse rotation angle"); print_usage(); exit(EXIT_FAILURE); } if ((raw_angle > 270) || (raw_angle % 90)) { LOG("invalid rotation angle"); print_usage(); exit(EXIT_FAILURE); } rotation_angle = raw_angle; } break; case 'g': if (str2ul(optarg, &pause_ms) < 0) { LOG("failed to parse pause duration"); print_usage(); exit(EXIT_FAILURE); } break; case 'f': if (optarg == NULL) { cfa = PLDRAW_CFA_GR_BW; } else { cfa = pldraw_get_cfa_id(optarg); if (cfa < 0) { LOG("Invalid CFA identifier: %s", optarg); print_usage(); exit(EXIT_FAILURE); } } break; case 'W': do_enumerate_waveforms = 1; break; case 'w': waveform_id_str = optarg; break; case 'm': mode = optarg; break; case 'd': fbdev = optarg; break; case 'e': epdev = optarg; break; case 'b': background = optarg; break; case 't': doc_type = optarg; break; case 'o': if (parse_offset(&offset, optarg) < 0) { print_usage(); exit(EXIT_FAILURE); } break; case 'a': if (parse_alignment(&align_h, &align_v, optarg) < 0) { print_usage(); exit(EXIT_FAILURE); } break; case 'c': if (parse_crop(&crop, optarg) < 0) { print_usage(); exit(EXIT_FAILURE); } break; case 'O': conf_file = optarg; if (access(conf_file, F_OK)) { LOG_ERRNO("Configuration file"); exit(EXIT_FAILURE); } break; case '?': default: LOG("Invalid arguments"); print_usage(); exit(EXIT_FAILURE); break; } } if (optind < argc) { file_names = &argv[optind]; n_files = argc - optind; } LOG("%s v%s", APP_NAME, VERSION); plep = plep_init(epdev, mode, conf_file); if (plep == NULL) { LOG("failed to initialise ePDC"); goto error_plep; } pldraw = pldraw_init(fbdev, conf_file); if (pldraw == NULL) { LOG("failed to initialise pldraw"); goto error_pldraw; } pldraw_set_plep(pldraw, plep); waveform_id = plep_get_wfid(plep, waveform_id_str); if (waveform_id < 0) { LOG("Invalid waveform path: %s", waveform_id_str); goto error_pldraw; } if (cfa >= 0) pldraw_set_cfa(pldraw, cfa); else cfa = pldraw_get_cfa(pldraw); if (cfa != PLDRAW_CFA_NONE) LOG("CFA: %s", pldraw_cfa_name[cfa]); if (rotation_angle < 0) rotation_angle = pldraw_get_rotation(pldraw); if (rotation_angle) LOG("rotation: %d", rotation_angle); if (do_log_info) pldraw_log_info(pldraw); sigint_original = signal(SIGINT, sigint_abort); if (do_enumerate_waveforms) { ret = enumerate_waveforms(plep); } else { struct epdoc_opt opt; plep_set_opt(plep, PLEP_SYNC_UPDATE, do_synchro); if (do_wait_power_off) plep_set_opt(plep, PLEP_WAIT_POWER_OFF, 1); opt.do_auto_rotate = do_auto_rotate; opt.rotation_angle = rotation_angle; opt.wfid = waveform_id; opt.offset.x = offset.x; opt.offset.y = offset.y; opt.align_h = align_h; opt.align_v = align_v; memcpy(&opt.crop, &crop, sizeof opt.crop); opt.doc_type = doc_type; ret = show_contents(pldraw, file_names, n_files, &opt, pause_ms, do_infinite_loop, background); } signal(SIGINT, sigint_original); pldraw_free(pldraw); plep_free(plep); exit((ret < 0) ? EXIT_FAILURE : EXIT_SUCCESS); error_pldraw: plep_free(plep); error_plep: exit(EXIT_FAILURE); }