%% options copyright owner = Dirk Krause copyright year = 2011-2014 license = bsd %% module #include "dk3all.h" #include "dkt.h" $!trace-include /** Job structure for dkt blks. */ typedef struct { dk3_app_t *app; /**< Application. */ dkChar const * const *msg; /**< Localized messages. */ dkChar const * const *kwnl; /**< Keywords, not localized. */ dk3_option_set_t *opt; /**< Option set. */ char *ib; /**< Input buffer. */ char *ob; /**< Output buffer. */ size_t oblgt; /**< Output buffer length. */ size_t obused; /**< Output buffer used. */ int exval; /**< Exit status code. */ int f_oer; /**< Flag: Output error reported. */ int f_sim; /**< Flag: Simple read, write operations. */ } DKT_BLKS_J; /** Options used by dkt blks. */ static dk3_option_t const dkt_blks_options[] = { { dkT('R'), dkT("reset"), 0 }, { dkT('b'), dkT("block-size"), 1 }, { dkT('s'), dkT("simple"), 0 } }; /** Keywords available in configuration file. */ static dkChar const * const dkt_blks_conf_kw[] = { dkT("block-size"), dkT("simple"), NULL }; /** Number of options in the dkt_blks_options array. */ static size_t const dkt_blks_szoptions = sizeof(dkt_blks_options)/sizeof(dk3_option_t); /** Initialize job structure. @param j Structure to initialize. */ static void dkt_blks_job_init(DKT_BLKS_J *j) { $? "+ dkt_blks_job_init" j->opt = NULL; j->ib = NULL; j->ob = NULL; j->oblgt = 512; $? ". reset oblgt" j->obused = 0; j->exval = DKT_RESULT_ERR_UNSPECIFIC; j->f_oer = 0; j->f_sim = 0; $? "- dkt_blks_job_init" } /** Clean up job structure. @param j Job structure to clean up. */ static void dkt_blks_job_cleanup(DKT_BLKS_J *j) { if(j->opt) { dk3opt_close(j->opt); } j->opt = NULL; $? "= dkt_blks_job_cleanup" } #if VERSION_BEFORE_20140808 /** Find last character in text. @param txt Text to inspect. @return Pointer to last character of text, or NULL. */ static dkChar * dkt_blks_lastchar(dkChar *txt) { dkChar *back = NULL; while (dkT('\0') != *txt) { back = txt; txt++; } return back; } #endif /** Set output buffer length. @param rp Pointer to output buffer length variable. @param txt Text containing the size, suffix 'M' or 'k' allowed. @param app Application structure for diagnostics, may be NULL. @return 1 on success, 0 on error. */ static int dkt_blks_set_blocksize(size_t *rp, dkChar *txt, DKT_BLKS_J *j, dk3_app_t *app) { #if VERSION_BEFORE_20140808 dkChar *lptr = NULL; /* Pointer to last character */ dkChar savedc = dkT('\0'); /* Saved size character */ dk3_um_t r1; /* Number read from text */ dk3_um_t fa = DK3_UM_1; /* Factor for suffix */ size_t rx; int ec = 0; /* Math error code */ int back = 0; /* Result */ $? "+ dkt_blks_set_blocksize \"%s\"", txt #if 0 /* Just to debug the dk3ma_sz_from_string() function. */ (void)dk3ma_sz_from_string(&rx, txt, NULL); #endif lptr = dkt_blks_lastchar(txt); if (NULL != lptr) { $? ". last char found" switch (*lptr) { case dkT('g'): case dkT('G') : { $? ". G" savedc = *lptr; fa = dk3ma_um_mul_ok( dk3ma_um_mul_ok((dk3_um_t)1024, (dk3_um_t)1024, &ec), (dk3_um_t)1024, &ec ); *lptr = dkT('\0'); } break; case dkT('m'): case dkT('M') : { $? ". M" savedc = *lptr; fa = dk3ma_um_mul_ok((dk3_um_t)1024, (dk3_um_t)1024, &ec); *lptr = dkT('\0'); $? ". fa = %lu", (unsigned long)fa } break; case dkT('k') : case dkT('K') : { $? ". k" savedc = *lptr; fa = (dk3_um_t)1024; *lptr = dkT('\0'); $? ". fa = %lu", (unsigned long)fa } break; default: { savedc = dkT('\0'); } break; } } if (dk3ma_um_from_string(&r1, txt, &ec)) { if (NULL != lptr) { if (dkT('\0') != savedc) { *lptr = savedc; } } #if DK3_ON_WINDOWS $? ". r1 = %I64uu", r1 #else $? ". r1 = %ju", r1 #endif ec = 0; r1 = dk3ma_um_mul_ok(r1, fa, &ec); if (0 == ec) { $? ". Multiplication ok" #if DK3_ON_WINDOWS $? ". r1 = %I64u", r1 #else $? ". r1 = %ju", r1 #endif if (sizeof(dk3_um_t) > sizeof(size_t)) { $? ". sizeof check" if(r1 <= (dk3_um_t)DK3_SIZE_T_MAX) { $? ". size ok" *rp = (size_t)r1; if (((dk3_um_t)DK3_SIZE_T_MAX / (dk3_um_t)2) >= r1) { back = 1; } else { /* ERROR: Buffer size too large */ if (NULL != app) { j->exval = DKT_RESULT_ERR_OPTION; dk3app_log_3(app, DK3_LL_ERROR, j->msg, 15, 16, txt); } } } else { $? "! overflow" if (NULL != app) { /* Math overflow */ j->exval = DKT_RESULT_ERR_OPTION; dk3app_log_3(app, DK3_LL_ERROR, j->msg, 15, 16, txt); } } } else { $? ". sizeof ok" *rp = (size_t)r1; if (((dk3_um_t)DK3_SIZE_T_MAX / (dk3_um_t)2) >= r1) { back = 1; } else { if (NULL != app) { /* ERROR: Buffer size too large */ dk3app_log_3(app, DK3_LL_ERROR, j->msg, 15, 16, txt); j->exval = DKT_RESULT_ERR_OPTION; } } } } else { $? ". overflow in mult" if (NULL != app) { /* ERROR: Numeric overflow */ j->exval = DKT_RESULT_ERR_OPTION; dk3app_log_3(app, DK3_LL_ERROR, j->msg, 15, 16, txt); } } } else { if (NULL != app) { switch (ec) { case DK3_ERROR_SYNTAX: { /* ERROR: Not a number */ j->exval = DKT_RESULT_ERR_OPTION; dk3app_log_i3(app, DK3_LL_ERROR, 141, 142, txt); } break; case DK3_ERROR_MATH_OVERFLOW: { /* ERROR: Numeric overflow */ j->exval = DKT_RESULT_ERR_OPTION; dk3app_log_3(app, DK3_LL_ERROR, j->msg, 15, 16, txt); } break; default: { /* ERROR: Failed to obtain number, reason unknonw */ j->exval = DKT_RESULT_ERR_OPTION; if (NULL != app) { dk3app_log_i3(app, DK3_LL_ERROR, 141, 142, txt); } } break; } } } $? "- dkt_blks_set_blocksize %d", back return back; #else /* 2014-08-27 Now use the dkt_tool_set_size() function. */ return (dkt_tool_set_size(rp, txt, j->msg, j->kwnl, j->app, &(j->exval))); #endif } /** Process one key/value pair. @param jv Pointer to job structure casted to void *. @param k Key. @param v Value. @return 1 to indicate success. */ static int dkt_blks_conf_line(void *jv, dkChar const *k, dkChar const *v) { dkChar buf[64]; int back = 0; #if VERSION_BEFORE_20140808 unsigned u = 512; /* Variable for block size. */ #endif DKT_BLKS_J *j = NULL; /* Job structure. */ $? "+ dkt_blks_conf_line \"%s\"=\"%s\"", TR_STR(k), TR_STR(v) j = (DKT_BLKS_J *)jv; switch(dk3str_array_index(dkt_blks_conf_kw, k, 0)) { case 0: { if(v) { #if VERSION_BEFORE_20140807 #if VERSION_BEFORE_20140716 if(dk3sf_sscanf3(v, dkT("%u"), &u) > 0) #else if(0 != dk3ma_ui_from_string(&u, v, NULL)) #endif { j->oblgt = (size_t)u; back = 1; $? ". oblgt=%u", (unsigned)(j->oblgt) } #else if (dk3str_len(v) < DK3_SIZEOF(buf,dkChar)) { dk3str_cpy(buf, v); if (dkt_blks_set_blocksize(&(j->oblgt), buf, j, NULL)) { } } else { /* ERROR: Size specification too long! (Silently ignored) */ /* dk3app_log_i3(j->app, DK3_LL_ERROR, 135, 136, v); */ } #endif } } break; case 1: { if(v) { if(dk3str_is_bool(v)) { j->f_sim = ((dk3str_is_on(v)) ? 1 : 0); } else { /* Error in configuration file */ } } else { j->f_sim = 1; } } break; } $? "- dkt_blks_conf_line %d", back return back; } /** Process the command line arguments. @param j Job structure. @return 1 on success, 0 on error. */ static int dkt_blks_process_arguments(DKT_BLKS_J *j) { dkChar buf[64]; int back = 0; int xargc = 0; /* Number of command line arguments. */ #if VERSION_BEFORE_20140809 unsigned u = 512; /* Variable for block size. */ #endif dkChar const *arg = NULL; /* Current argument to process. */ dkChar const * const *xargv = NULL; /* Command line arguments array. */ $? "+ dkt_blks_process_arguments" xargc = dk3app_get_argc(j->app); xargv = dk3app_get_argv(j->app); xargv++; xargv++; xargc--; xargc--; j->opt = dk3opt_open_app( dkt_blks_options, dkt_blks_szoptions, dkT('\0'), NULL, xargc, xargv, j->app ); if(j->opt) { if(0 == dk3opt_get_error_code(j->opt)) { back = 1; if(dk3opt_is_set(j->opt, dkT('R'))) { j->f_sim = 0; j->oblgt = 512; $? ". oblgt=512" } if(dk3opt_is_set(j->opt, dkT('s'))) { j->f_sim = 1; } if(dk3opt_is_set(j->opt, dkT('b'))) { $? ". have -b" arg = dk3opt_get_short_arg(j->opt, dkT('b')); if(arg) { $? ". arg=%s", arg #if VERSION_BEFORE_20140807 #if VERSION_BEFORE_20140809 if(dk3sf_sscanf3(arg, dkT("%u"), &u) > 0) { $? ". sscanf ok %u", u j->oblgt = (size_t)u; $? ". oblgt=%u", (unsigned)(j->oblgt) if((unsigned)(j->oblgt) != u) { $? "! overflow" back = 0; j->exval = DKT_RESULT_ERR_OPTION; /* ERROR: Overflow. */ dk3app_log_3(j->app, DK3_LL_ERROR, j->msg, 15, 16, arg); } } else { $? "! sscanf failed" back = 0; j->exval = DKT_RESULT_ERR_OPTION; /* ERROR: Not a number. */ dk3app_log_i3(j->app, DK3_LL_ERROR, 141, 142, arg); } #else dk3_um_t um = DK3_UM_0; #if VERSION_BEFORE_20140716 if (dk3ma_string_to_um(&um, arg)) #else if (0 != dk3ma_um_from_string(&um, arg, NULL)) #endif { if (DK3_UM_0 != um) { j->oblgt = dk3ma_um_to_sz(um, NULL); if (0 == j->oblgt) { /* Overflow */ back = 0; j->exval = DKT_RESULT_ERR_OPTION; dk3app_log_3(j->app, DK3_LL_ERROR, j->msg, 15, 16, arg); } } else { /* 0 */ back = 0; j->exval = DKT_RESULT_ERR_OPTION; dk3app_log_i3(j->app, DK3_LL_ERROR, 141, 142, arg); } } else { /* Not a number */ back = 0; j->exval = DKT_RESULT_ERR_OPTION; dk3app_log_i3(j->app, DK3_LL_ERROR, 141, 142, arg); } #endif #else if (dk3str_len(arg) < DK3_SIZEOF(buf,dkChar)) { dk3str_cpy(buf, arg); if (0 == dkt_blks_set_blocksize(&(j->oblgt), buf, j, j->app)) { back = 0; } } else { /* ERROR: Size specification too long! */ dk3app_log_i3(j->app, DK3_LL_ERROR, 135, 136, arg); j->exval = DKT_RESULT_ERR_OPTION; } #endif } else { back = 0; j->exval = DKT_RESULT_ERR_OPTION; } } } else { j->exval = DKT_RESULT_ERR_OPTION; } } else { j->exval = DKT_RESULT_ERR_OPTION; } $? "- dkt_blks_process_arguments %d", back return back; } /** Flush output buffer to standard output. @param j Job structure. */ static void dkt_blks_flush_output(DKT_BLKS_J *j) { $? "+ dkt_blks_flush_output" if(j->obused > 0) { $? ". have bytes %u", (unsigned)(j->obused) if(!dk3sf_write_app(1, j->ob, j->obused, j->app)) { /* ERROR while writing output! */ j->exval = DKT_RESULT_ERR_OUTPUT; if(!(j->f_oer)) { dk3app_log_i1(j->app, DK3_LL_ERROR, 120); } j->f_oer = 0; } } $? "- dkt_blks_flush_output" } /** Add one character to output buffer, flush if necessary (buffer full). @param j Job structure. @param c Character to add. */ static void dkt_blks_add_char(DKT_BLKS_J *j, char c) { $? "+ dkt_blks_add_char" (j->ob)[j->obused] = c; j->obused += 1; if(j->obused >= j->oblgt) { dkt_blks_flush_output(j); j->obused = 0; } $? "- dkt_blks_add_char" } /** Process one input file. @param j Job structure. @param fipo File pointer to read input file. */ static void dkt_blks_process_file(DKT_BLKS_J *j, FILE *fipo) { size_t rdbytes = 0; /* Bytes read in current pass. */ size_t i = 0; /* Index of current byte to process. */ $? "+ dkt_blks_process_file" do { rdbytes = dk3sf_fread_app((void *)(j->ib), 1, j->oblgt, fipo, j->app); if(rdbytes > 0) { for(i = 0; i < rdbytes; i++) { dkt_blks_add_char(j, (j->ib)[i]); } } } while(rdbytes > 0); $? "- dkt_blks_process_file" } #if 0 /* Initial version, not optimized. */ /** Process standard input. @param j Job structure. */ static void dkt_blks_stdin_run(DKT_BLKS_J *j) { size_t rdbytes = 0; /* Number of bytes read from stdin. */ size_t i = 0; /* Index of current byte to process. */ #if DK3_ON_WINDOWS int oldmode; /* Old stdin mode. */ #endif #if DK3_ON_WINDOWS oldmode = _setmode(0, _O_BINARY); #endif $? "+ dkt_blks_stdin_run" do { $? ". start of loop" rdbytes = dk3sf_read_app(0, j->ib, j->oblgt, j->app); $? ". bytes received = %u", (unsigned)rdbytes if(rdbytes > 0) { for(i = 0; i < rdbytes; i++) { dkt_blks_add_char(j, (j->ib)[i]); } } } while(rdbytes > 0); if(j->obused) { dkt_blks_flush_output(j); } #if DK3_ON_WINDOWS _setmode(0, oldmode); #endif $? "- dkt_blks_stdin_run" } #endif #if 0 /* Not optimized. */ /** Process standard input. @param j Job structure. */ static void dkt_blks_stdin_run(DKT_BLKS_J *j) { char *sptr; /* Source pointer, ib. */ char *dptr; /* Destination pointer, ob. */ size_t obu; /* Used bytes in output buffer. */ size_t rdb; /* Bytes in input buffer. */ size_t obusz; /* Output buffer size. */ size_t i; /* Index of current input byte. */ int cc; /* Flag: Can continue. */ int we; /* Write error. */ #if DK3_ON_WINDOWS int oldmode; /* Old stdin mode. */ #endif #if DK3_ON_WINDOWS oldmode = _setmode(0, _O_BINARY); #endif we = 0; obusz = j->oblgt; obu = 0; dptr = j->ob; /* Read input. */ while(cc) { rdb = dk3sf_read_app(0, j->ib, j->oblgt, j->app); if(rdb > 0) { sptr = j->ib; for(i = 0; i < rdb; i++) { *(dptr++) = *(sptr++); if(++obu >= obusz) { if(!dk3sf_write_app(1, j->ob, obu, j->app)) { j->exval = DKT_RESULT_ERR_OUTPUT; dk3app_log_i1(j->app, DK3_LL_ERROR, 120); we = 1; cc = 0; i = rdb; } obu = 0; dptr = j->ob; } } } else { cc = 0; } } /* Flush final (partial) block. */ if(obu) { if(!(we)) { if(!dk3sf_write_app(1, j->ob, obu, j->app)) { j->exval = DKT_RESULT_ERR_OUTPUT; dk3app_log_i1(j->app, DK3_LL_ERROR, 120); we = 1; } } } #if DK3_ON_WINDOWS _setmode(0, oldmode); #endif } #endif #if 0 /* Optimization step 2: Local variables, separate code for Windows and others */ /** Process standard input. @param j Job structure. */ static void dkt_blks_simple_stdin_run(DKT_BLKS_J *j) { #if DK3_ON_WINDOWS char *sptr; char *dptr; size_t obu; size_t bs; int rdb; int wrb; int i; int cc; int ec; int oldmode; oldmode = _setmode(0, _O_BINARY); ec = 0; cc = 1; dptr = j->ob; bs = j->oblgt; obu = 0; while(cc) { rdb = _read(0, j->ib, (unsigned int)(j->oblgt)); if(0 < rdb) { sptr = j->ib; for(i = 0; i < rdb; i++) { *(dptr++) = *(sptr++); if(++obu >= bs) { wrb = _write(1, j->ob, (unsigned int)obu); if(wrb < (int)obu) { cc = 0; ec = 1; i = rdb; } dptr = j->ob; obu = 0; } } } else { cc = 0; } } if((obu) && (0 == ec)) { wrb = _write(1, j->ob, (unsigned int)obu); if(wrb < (int)obu) { ec = 1; } } _setmode(0, oldmode); if(ec) { j->exval = DKT_RESULT_ERR_OUTPUT; dk3app_log_i1(j->app, DK3_LL_ERROR, 120); } #else char *sptr; char *dptr; size_t obu; size_t bs; ssize_t rdb; ssize_t i; ssize_t wrb; int cc; int ec; ec = 0; cc = 1; dptr = j->ob; bs = j->oblgt; obu = 0; while(cc) { rdb = read(0, j->ib, j->oblgt); if(0 < rdb) { sptr = j->ib; for(i = 0; i < rdb; i++) { *(dptr++) = *(sptr++); if(++obu >= bs) { wrb = write(1, j->ob, obu); if(wrb < (ssize_t)obu) { cc = 0; ec = 1; i = rdb; } dptr = j->ob; obu = 0; } } } else { cc = 0; } } if((obu) && (0 == ec)) { wrb = write(1, j->ob, obu); if(wrb < (ssize_t)obu) { ec = 1; } } if(ec) { j->exval = DKT_RESULT_ERR_OUTPUT; dk3app_log_i1(j->app, DK3_LL_ERROR, 120); } #endif } #endif #if 0 /* Optimization step 2: Macros for read()/_read() and write()/_write(). */ /** Process standard input. @param j Job structure. */ static void dkt_blks_simple_stdin_run(DKT_BLKS_J *j) { char *sptr; char *dptr; size_t obu; size_t bs; dk3_rw_res_t rdb; dk3_rw_res_t wrb; int i; int cc; int ec; #if DK3_ON_WINDOWS int oldmode; oldmode = _setmode(0, _O_BINARY); #endif ec = 0; cc = 1; dptr = j->ob; bs = j->oblgt; obu = 0; while(cc) { rdb = dk3sf_read_app(0,j->ib,(dk3_rw_arg_t)(j->oblgt), NULL); if(0 < rdb) { sptr = j->ib; for(i = 0; i < rdb; i++) { *(dptr++) = *(sptr++); if(++obu >= bs) { wrb = dk3sf_write_app(1, j->ob, (dk3_rw_arg_t)obu, NULL); if(wrb < (dk3_rw_res_t)obu) { cc = 0; ec = 1; i = rdb; } dptr = j->ob; obu = 0; } } } else { cc = 0; } } if((obu) && (0 == ec)) { wrb = dk3sf_write_app(1, j->ob, (dk3_rw_arg_t)obu, NULL); if(wrb < (dk3_rw_res_t)obu) { ec = 1; } } #if DK3_ON_WINDOWS _setmode(0, oldmode); #endif if(ec) { j->exval = DKT_RESULT_ERR_OUTPUT; dk3app_log_i1(j->app, DK3_LL_ERROR, 120); } } #endif /** Process standard input. @param j Job structure. */ static void dkt_blks_stdin_run(DKT_BLKS_J *j) { char *saddr; /* Address of source buffer. */ char *daddr; /* Address of destination buffer. */ char *sptr; /* Source pointer. */ char *dptr; /* Destination pointer. */ size_t obu; /* Used bytes in output buffer. */ size_t bs; /* Buffer size (both input and output). */ size_t rem; /* Remaining bytes to process. */ size_t cpb; /* Bytes to copy. */ size_t rdb; /* Bytes read. */ int cc; /* Flag: Can continue. */ int ec; /* Flag: Error found. */ #if DK3_ON_WINDOWS int oldmode; oldmode = _setmode(0, _O_BINARY); #endif saddr = j->ib; daddr = j->ob; sptr = saddr; dptr = daddr; bs = j->oblgt; obu = 0; cc = 1; ec = 0; while(cc) { rdb = dk3sf_read_app(0, saddr, bs, j->app); if(0 < rdb) { rem = rdb; sptr = saddr; while(rem) { cpb = bs - obu; if(rem < cpb) { cpb = rem; } dk3mem_cpy(dptr,sptr,cpb); obu += cpb; sptr = &(sptr[cpb]); rem -= cpb; if(obu >= bs) { if(0 == dk3sf_write_app(1, daddr, obu, j->app)) { rem = 0; cc = 0; ec = 1; } obu = 0; dptr = daddr; } else { dptr = &(dptr[cpb]); } } } else { cc = 0; } } if((obu) && (0 == ec)) { if(0 == dk3sf_write_app(1, daddr, obu, j->app)) { ec = 1; } } #if DK3_ON_WINDOWS _setmode(0, oldmode); #endif if(ec) { j->exval = DKT_RESULT_ERR_OUTPUT; dk3app_log_i1(j->app, DK3_LL_ERROR, 120); } } /** Process standard input. @param j Job structure. */ static void dkt_blks_simple_stdin_run(DKT_BLKS_J *j) { char *saddr; /* Address of source buffer. */ char *daddr; /* Address of destination buffer. */ char *sptr; /* Source pointer. */ char *dptr; /* Destination pointer. */ size_t obu; /* Used bytes in output buffer. */ size_t bs; /* Buffer size (both input and output). */ size_t rem; /* Remaining bytes to process. */ size_t cpb; /* Bytes to copy. */ dk3_rw_res_t rdb; /* Bytes read. */ dk3_rw_res_t wrb; /* Bytes written. */ int cc; /* Flag: Can continue. */ int ec; /* Flag: Error found. */ #if DK3_ON_WINDOWS int oldmode; oldmode = _setmode(0, _O_BINARY); #endif $? "+ dkt_blks_simple_stdin_run" saddr = j->ib; daddr = j->ob; sptr = saddr; dptr = daddr; bs = j->oblgt; obu = 0; cc = 1; ec = 0; while(cc) { rdb = dk3sf_read_app(0,saddr,(dk3_rw_arg_t)bs, NULL); if(0 < rdb) { rem = (size_t)rdb; sptr = saddr; while(rem) { cpb = bs - obu; if(rem < cpb) { cpb = rem; } dk3mem_cpy(dptr,sptr,cpb); obu += cpb; sptr = &(sptr[cpb]); rem -= cpb; if(obu >= bs) { wrb = dk3sf_write_app(1,daddr,(dk3_rw_arg_t)obu, NULL); if(wrb < (dk3_rw_res_t)obu) { rem = 0; cc = 0; ec = 1; } obu = 0; dptr = daddr; } else { dptr = &(dptr[cpb]); } } } else { cc = 0; $? ". end of input" } } if((obu) && (0 == ec)) { wrb = dk3sf_write_app(1,daddr,(dk3_rw_arg_t)obu, NULL); if(wrb < (dk3_rw_res_t)obu) { ec = 1; } } #if DK3_ON_WINDOWS _setmode(0, oldmode); #endif if(ec) { j->exval = DKT_RESULT_ERR_OUTPUT; dk3app_log_i1(j->app, DK3_LL_ERROR, 120); } $? "- dkt_blks_simple_stdin_run" } /** Process one real file name (after correction and expansion). @param j Job structure. @param en Entry name. */ static void dkt_blks_process_one_real_name(DKT_BLKS_J *j, dkChar const *en) { FILE *fipo = NULL; /* File pointer to read input file. */ $? "+ dkt_blks_process_one_real_name \"%s\"", TR_STR(en) fipo = dk3sf_fopen_app(en, dk3app_not_localized(36), j->app); if(fipo) { dkt_blks_process_file(j, fipo); fclose(fipo); } else { /* ERROR: Failed to open file */ j->exval = DKT_RESULT_ERR_FILENAME; } $? "- dkt_blks_process_one_real_name" } /** Process all the file names specified on the command line. @param j Job structure. @param nfn Number of file names. */ static void dkt_blks_process_filenames(DKT_BLKS_J *j, int nfn) { dkChar const *arg = NULL; /* Current argument. */ dkChar const *en = NULL; /* File name. */ dkChar fnb[DK3_MAX_PATH]; /* Copy of file name. */ int i = 0; /* Current argument index. */ dk3_dir_t *fne = NULL; /* File name expander. */ $? "+ dkt_blks_process_filenames" for(i = 0; i < nfn; i++) { arg = dk3opt_get_arg(j->opt, i); if(arg) { if(dk3str_len(arg) < DK3_SIZEOF(fnb,dkChar)) { dk3str_cpy_not_overlapped(fnb, arg); dk3str_correct_filename(fnb); if(dk3sf_must_expand(fnb)) { fne = dk3dir_fne_open_app(fnb, j->app); if(fne) { if(dk3dir_get_number_of_files(fne) > 0) { while(dk3dir_get_next_file(fne)) { en = dk3dir_get_fullname(fne); if(en) { dkt_blks_process_one_real_name(j, en); } else { /* BUG */ } } } else { /* ERROR: No such file! */ dk3app_log_i3(j->app, DK3_LL_ERROR, 215, 216, fnb); j->exval = DKT_RESULT_ERR_FILENAME; } dk3dir_close(fne); } else { /* ERROR: Expander */ j->exval = DKT_RESULT_ERR_MEMORY; } } else { dkt_blks_process_one_real_name(j, fnb); } } else { /* ERROR: Name too long! */ dk3app_log_i3(j->app, DK3_LL_ERROR, 65, 66, arg); j->exval = DKT_RESULT_ERR_FILENAME; } } else { /* BUG */ } } $? "- dkt_blks_process_filenames" } /** Run with buffers. @param j Job structure. */ static void dkt_blks_run_with_buffers(DKT_BLKS_J *j) { int nfn = 0; /* Number of file names. */ #if DK3_ON_WINDOWS int oldmode = _O_TEXT; /* Old stdout mode. */ #endif $? "+ dkt_blks_run_with_buffers" #if DK3_ON_WINDOWS oldmode = _setmode(1, _O_BINARY); #endif nfn = dk3opt_get_num_args(j->opt); if(nfn > 0) { dkt_blks_process_filenames(j, nfn); if(j->obused) { dkt_blks_flush_output(j); } } else { if(j->f_sim) { dkt_blks_simple_stdin_run(j); } else { dkt_blks_stdin_run(j); } } #if DK3_ON_WINDOWS _setmode(1, oldmode); #endif $? "- dkt_blks_run_with_buffers" } /** Allocate buffers and run with buffers in dynamic memory. @param j Job structure. */ static void dkt_blks_run_with_allocated_buffers(DKT_BLKS_J *j) { char *ib = NULL; /* Input buffer dynamically allocated. */ char *ob = NULL; /* Output buffer dynamically allocated. */ $? "+ dkt_blks_run_with_allocated_buffers" ib = dk3_new_app(char,j->oblgt,j->app); if(ib) { ob = dk3_new_app(char,j->oblgt,j->app); if(ob) { j->ib = ib; j->ob = ob; dkt_blks_run_with_buffers(j); dk3_delete(ob); } else { j->exval = DKT_RESULT_ERR_MEMORY; } dk3_delete(ib); } else { j->exval = DKT_RESULT_ERR_MEMORY; } $? "- dkt_blks_run_with_allocated_buffers" } /** Run with builtin buffers. @param j Job structure. */ static void dkt_blks_run_with_internal_buffers(DKT_BLKS_J *j) { char ib[4096]; /* Builtin input buffer. */ char ob[4096]; /* Builtin output buffer. */ $? "+ dkt_blks_run_with_internal_buffers" j->ib = ib; j->ob = ob; dkt_blks_run_with_buffers(j); $? "- dkt_blks_run_with_internal_buffers" } /** Run a conversion. @param j Job structure. */ static void dkt_blks_run(DKT_BLKS_J *j) { $? "+ dkt_blks_run" if(j->oblgt > 4096) { dkt_blks_run_with_allocated_buffers(j); } else { dkt_blks_run_with_internal_buffers(j); } $? "- dkt_blks_run" } int dkt_blocksize( dk3_app_t *app, dkChar const *sn, dkChar const * const *msg, dkChar const * const *kwnl ) { int back = DKT_RESULT_ERR_UNSPECIFIC; DKT_BLKS_J j; /* Job structure. */ $? "+ dkt_blocksize" j.app = app; j.msg = msg; j.kwnl = kwnl; dkt_blks_job_init(&j); dkt_tool_read_conf(app, sn, (void *)(&j), dkt_blks_conf_line); if(dkt_blks_process_arguments(&j)) { j.exval = DKT_RESULT_OK; dkt_blks_run(&j); } back = j.exval; dkt_blks_job_cleanup(&j); $? "- dkt_blocksize %d", back return back; } /* vim: set ai sw=2 : */