"Fossies" - the Fresh Open Source Software Archive

Member "dateutils-0.4.6/src/dgrep.c" (19 Mar 2019, 6374 Bytes) of package /linux/privat/dateutils-0.4.6.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "dgrep.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 0.4.5_vs_0.4.6.

    1 /*** dgrep.c -- grep for lines with dates
    2  *
    3  * Copyright (C) 2011-2019 Sebastian Freundt
    4  *
    5  * Author:  Sebastian Freundt <freundt@ga-group.nl>
    6  *
    7  * This file is part of dateutils.
    8  *
    9  * Redistribution and use in source and binary forms, with or without
   10  * modification, are permitted provided that the following conditions
   11  * are met:
   12  *
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  *
   16  * 2. Redistributions in binary form must reproduce the above copyright
   17  *    notice, this list of conditions and the following disclaimer in the
   18  *    documentation and/or other materials provided with the distribution.
   19  *
   20  * 3. Neither the name of the author nor the names of any contributors
   21  *    may be used to endorse or promote products derived from this
   22  *    software without specific prior written permission.
   23  *
   24  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
   25  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   26  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   27  * DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   29  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   30  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
   31  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
   32  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
   33  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
   34  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   35  *
   36  **/
   37 #if defined HAVE_CONFIG_H
   38 # include "config.h"
   39 #endif  /* HAVE_CONFIG_H */
   40 #include <stdio.h>
   41 #include <stdlib.h>
   42 #include <stdint.h>
   43 #include <sys/time.h>
   44 #include <time.h>
   45 
   46 #include "dt-core.h"
   47 #include "dt-core-tz-glue.h"
   48 #include "dt-io.h"
   49 #include "dexpr.h"
   50 #include "dt-locale.h"
   51 #include "prchunk.h"
   52 
   53 const char *prog = "dgrep";
   54 
   55 
   56 /* dexpr subsystem */
   57 #include "dexpr.c"
   58 
   59 struct prln_ctx_s {
   60     struct grep_atom_soa_s *ndl;
   61     dexpr_t root;
   62     zif_t fromz;
   63     zif_t z;
   64     unsigned int only_matching_p:1U;
   65     unsigned int invert_match_p:1U;
   66 };
   67 
   68 static void
   69 proc_line(struct prln_ctx_s ctx, char *line, size_t llen)
   70 {
   71     char *osp = NULL;
   72     char *oep = NULL;
   73 
   74     /* check if line matches,
   75      * there's currently no way to specify NEEDLE */
   76     for (char *lp = line, *const zp = line + llen, *sp, *ep;
   77          /*no check*/; lp = ep, osp = sp, oep = ep) {
   78         struct dt_dt_s d =
   79             dt_io_find_strpdt2(
   80                 lp, zp - lp, ctx.ndl, &sp, &ep, ctx.fromz);
   81         bool unkp = dt_unk_p(d);
   82 
   83         if (unkp) {
   84             /* just plain nothing */
   85             break;
   86         } else if (ctx.z != NULL) {
   87             /* promote to zone ctx.z */
   88             d = dtz_enrichz(d, ctx.z);
   89         }
   90         /* otherwise */
   91         if (dexpr_matches_p(ctx.root, d)) {
   92             if (ctx.invert_match_p) {
   93                 /* nothing must match */
   94                 return;
   95             } else if (!ctx.only_matching_p) {
   96                 sp = line;
   97                 ep = line + llen;
   98             }
   99             /* make sure we finish the line */
  100             *ep++ = '\n';
  101             __io_write(sp, ep - sp, stdout);
  102             return;
  103         }
  104     }
  105     if (ctx.invert_match_p) {
  106         /* no match but invert_match select, print line */
  107         if (!ctx.only_matching_p) {
  108             osp = line;
  109             oep = line + llen;
  110         } else if (osp == NULL || oep == NULL) {
  111             /* no date in line and only-matching is active
  112              * bugger off */
  113             return;
  114         }
  115         /* finish the line and bugger off */
  116         *oep++ = '\n';
  117         __io_write(osp, oep - osp, stdout);
  118     }
  119     return;
  120 }
  121 
  122 
  123 #include "dgrep.yucc"
  124 
  125 int
  126 main(int argc, char *argv[])
  127 {
  128     yuck_t argi[1U];
  129     char **fmt;
  130     size_t nfmt;
  131     dexpr_t root;
  132     oper_t o = OP_UNK;
  133     int res = 0;
  134 
  135     if (yuck_parse(argi, argc, argv)) {
  136         res = 1;
  137         goto out;
  138     }
  139 
  140     /* init and unescape sequences, maybe */
  141     ckv_fmt = fmt = argi->input_format_args;
  142     ckv_nfmt = nfmt = argi->input_format_nargs;
  143     if (argi->backslash_escapes_flag) {
  144         for (size_t i = 0; i < nfmt; i++) {
  145             dt_io_unescape(fmt[i]);
  146         }
  147     }
  148     if (argi->base_arg) {
  149         struct dt_dt_s base = dt_strpdt(argi->base_arg, NULL, NULL);
  150         dt_set_base(base);
  151     }
  152 
  153     if (argi->eq_flag) {
  154         o = OP_EQ;
  155     } else if (argi->ne_flag) {
  156         o = OP_NE;
  157     } else if (argi->lt_flag || argi->ot_flag) {
  158         o = OP_LT;
  159     } else if (argi->le_flag) {
  160         o = OP_LE;
  161     } else if (argi->gt_flag || argi->nt_flag) {
  162         o = OP_GT;
  163     } else if (argi->ge_flag) {
  164         o = OP_GE;
  165     }
  166     /* parse the expression */
  167     if (argi->nargs == 0U || 
  168         dexpr_parse(&root, argi->args[0U], strlen(argi->args[0U])) < 0) {
  169         res = 1;
  170         error("Error: need an expression to grep");
  171         goto out;
  172     }
  173     /* fixup o, default is OP_EQ */
  174     if (o != OP_UNK && root->type != DEX_VAL) {
  175         res = 1;
  176         error("\
  177 long opt operators (--lt, --gt, ...) cannot be used in conjunction \n\
  178 with complex expressions");
  179         goto out;
  180     } else if (o != OP_UNK) {
  181         /* fiddle with the operator in the expression */
  182         root->kv->op = o;
  183     }
  184 
  185     if (argi->from_locale_arg) {
  186         setilocale(argi->from_locale_arg);
  187     }
  188 
  189     /* otherwise bring dexpr to normal form */
  190     dexpr_simplify(root);
  191     /* beef */
  192     {
  193         /* read from stdin */
  194         size_t lno = 0;
  195         struct grep_atom_s __nstk[16], *needle = __nstk;
  196         size_t nneedle = countof(__nstk);
  197         struct grep_atom_soa_s ndlsoa;
  198         void *pctx;
  199         struct prln_ctx_s prln = {
  200             .ndl = &ndlsoa,
  201             .root = root,
  202             .fromz = dt_io_zone(argi->from_zone_arg),
  203             .z = dt_io_zone(argi->zone_arg),
  204             .only_matching_p = argi->only_matching_flag,
  205             .invert_match_p = argi->invert_match_flag,
  206         };
  207 
  208         /* no threads reading this stream */
  209         __io_setlocking_bycaller(stdout);
  210 
  211         /* lest we overflow the stack */
  212         if (nfmt >= nneedle) {
  213             /* round to the nearest 8-multiple */
  214             nneedle = (nfmt | 7) + 1;
  215             needle = calloc(nneedle, sizeof(*needle));
  216         }
  217         /* and now build the needle */
  218         ndlsoa = build_needle(needle, nneedle, fmt, nfmt);
  219 
  220         /* using the prchunk reader now */
  221         if ((pctx = init_prchunk(STDIN_FILENO)) == NULL) {
  222             serror("Error: could not open stdin");
  223             goto ndl_free;
  224         }
  225         while (prchunk_fill(pctx) >= 0) {
  226             for (char *line; prchunk_haslinep(pctx); lno++) {
  227                 size_t llen = prchunk_getline(pctx, &line);
  228 
  229                 proc_line(prln, line, llen);
  230             }
  231         }
  232         /* get rid of resources */
  233         free_prchunk(pctx);
  234     ndl_free:
  235         if (needle != __nstk) {
  236             free(needle);
  237         }
  238     }
  239     /* resource freeing */
  240     free_dexpr(root);
  241     dt_io_clear_zones();
  242     if (argi->from_locale_arg) {
  243         setilocale(NULL);
  244     }
  245 out:
  246     yuck_free(argi);
  247     return res;
  248 }
  249 
  250 /* dgrep.c ends here */