pax_global_header00006660000000000000000000000064133504225700014513gustar00rootroot0000000000000052 comment=13deee53ac1bfde1e1fe89a55634f4737821d1b9 dateutils-0.4.5/000077500000000000000000000000001335042257000135175ustar00rootroot00000000000000dateutils-0.4.5/.drone.yml000066400000000000000000000005431335042257000154310ustar00rootroot00000000000000image: gcc4.8 script: - sudo apt-get install gperf - sudo apt-get install help2man - sudo apt-get install flex - sudo apt-get install bison - sudo apt-get install texinfo - sudo apt-get install texlive - autoreconf -vfi - ./configure - make clean all check - make distcheck notify: email: recipients: - devel@fresse.org dateutils-0.4.5/.gitattributes000066400000000000000000000000601335042257000164060ustar00rootroot00000000000000*.c linguist-language=C *.h linguist-language=C dateutils-0.4.5/.gitignore000066400000000000000000000005561335042257000155150ustar00rootroot00000000000000aclocal.m4 autom4te.cache configure ltmain.sh m4/libtool.m4 m4/lt*.m4 Makefile.in config.guess config.sub install-sh missing src/config.h.in *~ =build* build/ depcomp ++* Makefile .version version.mk config.log config.status libtool *.o config.h stamp-h1 .deps .libs texinfo.tex *.info test/*.log *.pc src/*-clo.[ch] info/*.h2m info/*.man ylwrap test-driver compile dateutils-0.4.5/.gitlab-ci.yml000066400000000000000000000012441335042257000161540ustar00rootroot00000000000000image: gcc:6.3 before_script: - apt-get -q -m update || true - apt-get install -qq gperf - apt-get install -qq flex - apt-get install -qq bison - apt-get install -qq texinfo - apt-get install -qq texlive - autoreconf -vfi pages: script: - ./configure --enable-tzmap-fetch --enable-contrib || { cat config.log; false; } - make - make check || { cat test/test-suite.log; false; } - make V=1 distcheck - mkdir -p public - cp dateutils-*.tar.* public/ - ln -sf dateutils-*.tar.xz public/dateutils-latest.tar.xz - ln -sf dateutils-*.tar.gz public/dateutils-latest.tar.gz artifacts: paths: - public only: - master dateutils-0.4.5/.travis.yml000066400000000000000000000042271335042257000156350ustar00rootroot00000000000000language: c sudo: false os: - linux compiler: - gcc - clang env: global: - secure: "GFjrqOUyqNLrPGtxNW4r9JxJBudjddBJFzEEcpPkfEbMHJ+kk4zOYsSLV1f1cAK+X8TWLsCq5Yjt/2Rzhu7Csjiy34RReZ9KwsmcwX78T8MkQQz4yv8by9J9a5mbHQ3S6mtF7PH1t38PKVcJi51icEqUjvi4FnfME5+VrdueE+c=" matrix: - CHECK="normal" matrix: include: ## distcheck - os: linux compiler: gcc env: CHECK="distcheck" ## Ubuntu 14.04 Trusty (beta), sudo required! - os: linux dist: trusty sudo: required compiler: gcc env: TRUSTY="yes" CHECK="normal" ## OSX - os: osx compiler: clang env: CHECK="normal" before_install: - if test "$TRUSTY" = "yes"; then echo -n | openssl s_client -connect scan.coverity.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | sudo tee -a /etc/ssl/certs/ca-certificates.crt; fi before_script: - autoreconf -vfi script: - if [ "$CHECK" = "normal" ]; then ./configure --enable-contrib || { cat config.log; false; } && make -j2 clean && make -j2 check; fi - if [ "$CHECK" = "distcheck" ]; then ./configure --enable-tzmap-fetch || { cat config.log; false; } && make -j2 all && make -j2 distcheck; fi after_script: # find test log from check as well as from distcheck - find -name test-suite.log | xargs -r cat ## whitelist branches: only: - master - next - coverity-scan - /^travis.*/ - /^tmp.*/ - /^v\d+\..*/ notifications: email: - devel@fresse.org addons: apt: packages: - gperf - texinfo - bison - flex - texlive coverity_scan: project: name: "hroptatyr/dateutils" description: "dateutils coverity scan" notification_email: devel@fresse.org build_command_prepend: "./configure" build_command: "make all check" branch_pattern: coverity-scan deploy: provider: releases api_key: secure: WRTz8MTXtkK69Hk/E1iXj4wXxko60vXgmcuW0RaLeRpmphUN9emVUu791W7fQeqx4j/GM32vwGPDa0jdm4dQ2s4ptNpEliisOpx/sGwJsugmeQm/5lSwTMuDwSWoIdWV7HRwsaWodXSzrxFBbZ9g+peTjz28geXp7lDtUCQbWC0= file_glob: true file: dateutils-*.tar.xz skip_cleanup: true on: tags: true dateutils-0.4.5/GNUmakefile000066400000000000000000000017471335042257000156020ustar00rootroot00000000000000# This GNUmakefile is used only if you run GNU Make. # If the user runs GNU make but has not yet run ./configure, # give them a diagnostic. _gl-Makefile := $(wildcard [M]akefile) ifneq ($(_gl-Makefile),) _dist-target_p ?= $(filter dist%,$(MAKECMDGOALS)) include Makefile # update the included makefile snippet which sets VERSION variables .PHONY: version.mk version.mk: .version version.mk.in -$(AM_V_GEN) \ if test "$(MAKECMDGOALS)" != "am--refresh"; then \ $(MAKE) -C "$(top_builddir)/build-aux" $(MAKECMDGOALS); \ PATH="$(top_builddir)/build-aux:$${PATH}" \ yuck scmver --ignore-noscm -o $@ --reference $^; \ if test $$? -eq 3 -a -n "$(_dist-target_p)"; then \ exec $(MAKE) $(MAKECMDGOALS); \ fi; \ fi else .DEFAULT_GOAL := abort-due-to-no-makefile $(MAKECMDGOALS): abort-due-to-no-makefile abort-due-to-no-makefile: @echo There seems to be no Makefile in this directory. 1>&2 @echo "You must run ./configure before running 'make'." 1>&2 exit 1 endif .PHONY: FORCE dateutils-0.4.5/INSTALL000066400000000000000000000013521335042257000145510ustar00rootroot00000000000000Installing dateutils from git tree ================================== Requisites: ----------- - compiler gcc >= 4.6.0 or compatible (icc, clang, ...) - autotools - texinfo - gperf - flex - bison Build and install: ------------------ - autoreconf -i - ./configure - make - [sudo] make install Installing dateutils from tarball ================================= Requisites: ----------- - compiler gcc >= 4.6.0 or compatible (icc, clang, ...) Build and install: ------------------ - ./configure - make - [sudo] make install Notes ===== To run the test suite in either case invoke - make check after building the binaries To kick off adoption, currently old/buggy gcc compilers are supported as well, however this might change in the future. dateutils-0.4.5/LICENSE000066400000000000000000000025651335042257000145340ustar00rootroot00000000000000Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. dateutils-0.4.5/Makefile.am000066400000000000000000000011701335042257000155520ustar00rootroot00000000000000include $(top_builddir)/version.mk LANG = C LC_ALL = C ACLOCAL_AMFLAGS = -I m4 SUBDIRS = EXTRA_DIST = $(DISTCLEANFILES) $(doc_DATA) DISTCLEANFILES = CLEANFILES = doc_DATA = SUBDIRS += build-aux SUBDIRS += data SUBDIRS += lib SUBDIRS += src SUBDIRS += info SUBDIRS += test if BUILD_MEXCLI SUBDIRS += contrib endif BUILD_MEXCLI if BUILD_OCTCLI SUBDIRS += contrib endif BUILD_OCTCLI DISTCLEANFILES += version.mk DISTCLEANFILES += .version EXTRA_DIST += version.mk.in doc_DATA += README.md doc_DATA += LICENSE ## make sure .version is read-only in the dist dist-hook: chmod ugo-w $(distdir)/.version ## Makefile.am ends here dateutils-0.4.5/README.md000066400000000000000000000306551335042257000150070ustar00rootroot00000000000000Dateutils ========= [![Build Status](https://secure.travis-ci.org/hroptatyr/dateutils.png?branch=master)](http://travis-ci.org/hroptatyr/dateutils) [![build status](https://gitlab.com/hroptatyr/dateutils/badges/master/build.svg)](https://gitlab.com/hroptatyr/dateutils/commits/master) [![Coverity Scan Build Status](https://scan.coverity.com/projects/2197/badge.svg)](https://scan.coverity.com/projects/2197) Dateutils are a bunch of tools that revolve around fiddling with dates and times on the command line with a strong focus on use cases that arise when dealing with large amounts of financial data. Dateutils are hosted primarily on github: + github page: + project homepage: + downloads: Below is a short list of examples that demonstrate what dateutils can do, for full specs refer to the info and man pages. For installation instructions refer to the INSTALL file. Dateutils commands are prefixed with a `date` but otherwise resemble known unix commands for reasons of intuition. The only exception being `strptime` which is analogous to the libc function of the same name. + `strptime` Command line version of the C function + `dateadd` Add durations to dates or times + `dateconv` Convert dates or times between calendars + `datediff` Compute durations between dates or times + `dategrep` Grep dates or times in input streams + `dateround` Round dates or times to "fuller" values + `dateseq` Generate sequences of dates or times + `datesort` Sort chronologically. + `datetest` Compare dates or times + `datezone` Convert date/times to timezones in bulk Examples ======== I love everything explained by example to get a first impression. So here it comes. dateseq ------- A tool mimicking seq(1) but whose inputs are from the domain of dates rather than integers. Typically scripts use something like $ for i in $(seq 0 9); do date -d "2010-01-01 +${i} days" "+%F" done which now can be shortened to $ dateseq 2010-01-01 2010-01-10 with the additional benefit that the end date can be given directly instead of being computed from the start date and an interval in days. Also, it provides date specific features that would be a PITA to implement using the above seq(1)/date(1) approach, like skipping certain weekdays: $ dateseq 2010-01-01 2010-01-10 --skip sat,sun => 2010-01-01 2010-01-04 2010-01-05 2010-01-06 2010-01-07 2010-01-08 dateseq also works on times: $ dateseq 12:00:00 5m 12:17:00 => 12:00:00 12:05:00 12:10:00 12:15:00 and also date-times: $ dateseq --compute-from-last 2012-01-02T12:00:00 5m 2012-01-02T12:17:00 => 2012-01-02T12:02:00 2012-01-02T12:07:00 2012-01-02T12:12:00 2012-01-02T12:17:00 dateconv -------- A tool to convert dates between different calendric systems and/or time zones. While other such tools usually focus on converting Gregorian dates to, say, the Chinese calendar, dconv aims at supporting calendric systems which are essential in financial contexts. To convert a (Gregorian) date into the so called ymcw representation: $ dateconv 2012-03-04 -f "%Y-%m-%c-%w" => 2012-03-01-00 and vice versa: $ dateconv 2012-03-01-Sun -i "%Y-%m-%c-%a" -f '%F' => 2012-03-04 where the ymcw representation means, the `%c`-th `%w` of the month in a given year. This is useful if dates are specified like, the third Thursday in May for instance. dateconv can also be used to convert occurrences of dates, times or date-times in an input stream on the fly $ dateconv -S -i '%b/%d %Y at %I:%M %P' < Remember we meet on 2012-03-03T14:30:00 and most prominently to convert between time zones: $ dateconv --from-zone "America/Chicago" --zone "Asia/Tokyo" 2012-01-04T09:33:00 => 2012-01-05T00:33:00 $ dateconv --zone "America/Chicago" now -f "%d %b %Y %T" => 05 Apr 2012 11:11:57 datetest -------- A tool to perform date comparison in the shell, it's modelled after `test(1)` but with proper command line options. $ if datetest today --gt 2010-01-01; then echo "yes" fi => yes dateadd ------- A tool to perform date arithmetic (date maths) in the shell. Given a date and a list of durations this will compute new dates. Given a duration and a list of dates this will compute new dates. $ dateadd 2010-02-02 +4d => 2010-02-06 $ dateadd 2010-02-02 +1w => 2010-02-09 $ dateadd -1d < 2001-01-04 2000-12-31 Adding durations to times: $ dateadd 12:05:00 +10m => 12:15:00 and even date-times: $ dateadd 2012-03-12T12:05:00 -1d4h => 2012-03-11T08:05:00 If supported by the system's zoneinfo database leap-second adjusted calculations are possible. Use the unit `rs` to denote "real" seconds: $ dateadd '2012-06-30 23:59:30' +30rs => 2012-06-30T23:59:60 as opposed to: $ dateadd '2012-06-30 23:59:30' +30s => 2012-07-01T00:00:00 datediff -------- A tool to calculate the difference between two (or more) dates. This is somewhat the converse of dadd. Outputs will be durations that, when added to the first date, give the second date. Get the number of days between two dates: $ datediff 2001-02-08 2001-03-02 => 22 The duration format can be controlled through the `-f` switch: $ datediff 2001-02-08 2001-03-09 -f "%m month and %d day" => 1 month and 1 day datediff also accepts time stamps as input: $ datediff 2012-03-01T12:17:00 2012-03-02T14:00:00 => 92580s The `-f` switch does the right thing: $ datediff 2012-03-01T12:17:00 2012-03-02T14:00:00 -f '%dd %Ss' => 1d 6180s compare to: $ datediff 2012-03-01T12:17:00 2012-03-02T14:00:00 -f '%dd %Hh %Ss' => 1d 1h 2580s If supported by the system's zoneinfo database leap-second adjusted calculations can be made. Use the format specifier `%rS` to get the elapsed time in "real" seconds: datediff '2012-06-30 23:59:30' '2012-07-01 00:00:30' -f '%rS' => 61 dategrep -------- A tool to extract lines from an input stream that match certain criteria, showing either the line or the match: $ dategrep '<2012-03-01' < Feb 2012-02-28 Feb 2012-02-29 leap day dateround --------- A tool to "round" dates or time stamps to a recurring point in time, like the next/previous January or the next/previous Thursday. Round (backwards) to the first of the current month: $ dateround '2011-08-22' -1 => 2011-08-01 Find the next Monday from the current date (today is 2016-01-08): $ dateround today Mon => 2015-01-11 Go back to last September, then round to the end of the month: $ dateround today -- -Sep +31d => 2015-09-30 Round a stream of dates strictly to the next month's first: $ dateround -S -n 1 < pay cable 2012-03-01 pay gas 2012-03-01 pay rent 2012-04-01 redeem loan 2012-04-01 Round a timeseries to the next minute (i.e. the seconds part is 00) and then to the next half-past time (and convert to ISO): $ dateround -S 0s30m -i '%d/%m/%Y %T' -f '%F %T' < 2012-03-06 14:30:00 eventA 2012-03-06 14:30:00 eventA 2012-03-06 14:30:00 eventB 2012-03-06 15:30:00 eventB Alternatively, if you divide the day into half-hours you can round to one of those using the co-class notation: $ dateround -S /30m -i '%d/%m/%Y %T' -f '%F %T' < 2012-03-06 14:30:00 eventA 2012-03-06 14:30:00 eventA 2012-03-06 14:30:00 eventB 2012-03-06 15:00:00 eventB This is largely identical to the previous example except, that a full hour (being an even multiple of half-hours) is a possible rounding target. datesort ----- A tool to bring the lines of a file into chronological order. At the moment the `datesort` tool depends on `sort(1)` with support for fields, in particular `-t` to select a separator and `-k` to sort by a particular field. $ datesort < 2009-06-03 caev="DVCA" secu="VOD" exch="XLON" xdte="2009-06-03" nett/GBX="5.2" 2010-11-17 caev="DVCA" secu="VOD" exch="XLON" xdte="2010-11-17" nett/GBX="2.85" 2011-11-16 caev="DVCA" secu="VOD" exch="XLON" xdte="2011-11-16" nett/GBX="3.05" 2012-06-06 caev="DVCA" secu="VOD" exch="XLON" xdte="2012-06-06" nett/GBX="6.47" 2013-06-12 caev="DVCA" secu="VOD" exch="XLON" xdte="2013-06-12" nett/GBX="6.92" 2013-11-20 caev="DVCA" secu="VOD" exch="XLON" xdte="2013-11-20" nett/GBX="3.53" datezone -------- A tool to quickly inspect date/time values in different timezones. The result will be a matrix that shows every date-time value in every timezone: $ datezone Europe/Berlin Australia/Sydney now 2014-06-30T05:00:00 => 2014-01-30T17:37:13+01:00 Europe/Berlin 2014-01-31T03:37:13+11:00 Australia/Sydney 2014-06-30T07:00:00+02:00 Europe/Berlin 2014-06-30T15:00:00+10:00 Australia/Sydney The `datezone` tool can also be used to obtain the next or previous DST transition relative to a given date/time: $ datezone --next Europe/Berlin Australia/Sydney 2013-02-19 => 2013-03-31T02:00:00+01:00 -> 2013-03-31T03:00:00+02:00 Europe/Berlin 2013-04-07T03:00:00+11:00 -> 2013-04-07T02:00:00+10:00 Australia/Sydney where the left time stamp denotes the current zone offset and the right side is the zone offset after the transition. The date/time indicates the exact moment when the transition is about to take place. In essence `datezone` is a better [`zdump(8)`][3]. strptime -------- A tool that brings the flexibility of [`strptime(3)`][1] to the command line. While (at least GNU) [`date(1)`][2] has support for output formats, it lacks any kind of support to read arbitrary input from the domain of dates, in particular when the input format is specifically known beforehand and only matching dates/times shall be considered. With the `strptime` tool reading weird dates like `Mon, May-01/2000` becomes a matter of strptime -i "%a, %b-%d/%Y" "Mon, May-01/2000" => 2000-05-01 just as you would have done in C. Note that `strptime` actually uses the system libc's strptime routine, and for output the system's strftime routine. Input and output modifiers will therefore vary between systems. For a portable parser/printer combination use `dateconv` as described above. Its input and output format specifiers are independent of the C runtime. Similar projects ================ In no particular order and without any claim to completeness: + dateexpr: + allanfalloon's dateutils: + yest + pdd Use the one that best fits your purpose. And in case you happen to like mine, vote: [dateutils' openhub page](https://www.openhub.net/p/dateutils) [1]: http://linux.die.net/man/3/strptime [2]: http://linux.die.net/man/1/date [3]: http://linux.die.net/man/8/zdump dateutils-0.4.5/build-aux/000077500000000000000000000000001335042257000154115ustar00rootroot00000000000000dateutils-0.4.5/build-aux/Makefile.am000066400000000000000000000002751335042257000174510ustar00rootroot00000000000000LANG = C LC_ALL = C AM_CFLAGS = $(EXTRA_CFLAGS) noinst_PROGRAMS = BUILT_SOURCES = EXTRA_DIST = DISTCLEANFILES = if !HAVE_YUCK include yuck.am endif !HAVE_YUCK ## Makefile.am ends here dateutils-0.4.5/build-aux/yuck-coru.c.m4000066400000000000000000000312051335042257000200160ustar00rootroot00000000000000/* -*- c -*- */ changequote`'changequote([,])dnl changecom([#])dnl #if defined HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #if defined HAVE_VERSION_H # include "version.h" #endif /* HAVE_VERSION_H */ #include #include #include #include #include changecom([])dnl ifdef([YUCK_HEADER], [dnl #include "YUCK_HEADER" ])dnl changecom([#])dnl #if defined __INTEL_COMPILER # pragma warning (push) # pragma warning (disable:177) # pragma warning (disable:111) # pragma warning (disable:3280) #elif defined __GNUC__ # if __GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 6 # pragma GCC diagnostic push # endif /* GCC version */ # pragma GCC diagnostic ignored "-Wunused-label" # pragma GCC diagnostic ignored "-Wunused-variable" # pragma GCC diagnostic ignored "-Wunused-function" # pragma GCC diagnostic ignored "-Wshadow" #endif /* __INTEL_COMPILER */ pushdef([DEFUN], ifdef([YUCK_HEADER], [], [static]))[]dnl static inline bool yuck_streqp(const char *s1, const char *s2) { return !strcmp(s1, s2); } /* for multi-args */ static inline char** yuck_append(char **array, size_t n, char *val) { if (!(n % 16U)) { /* resize */ void *tmp = realloc(array, (n + 16U) * sizeof(*array)); if (tmp == NULL) { free(array); return NULL; } /* otherwise make it persistent */ array = tmp; } array[[n]] = val; return array; } static enum yuck_cmds_e yuck_parse_cmd(const char *cmd) { if (0) { ; }foreachq([__CMD], yuck_cmds(), [ else if (yuck_streqp(cmd, "yuck_cmd_string(defn([__CMD]))")) { return yuck_cmd(defn([__CMD])); }]) else { /* error here? */ fprintf(stderr, "YUCK_UMB_STR: invalid command `%s'\n\ Try `--help' for a list of commands.\n", cmd); } return (enum yuck_cmds_e)-1; } DEFUN int yuck_parse(yuck_t tgt[[static 1U]], int argc, char *argv[[]]) { char *op; int i; /* we'll have at most this many args */ memset(tgt, 0, sizeof(*tgt)); if ((tgt->args = calloc(argc, sizeof(*tgt->args))) == NULL) { return -1; } ifdef([YUCK_MAX_POSARGS], [], [define([YUCK_MAX_POSARGS], [(size_t)-1])])dnl for (i = 1; i < argc && tgt->nargs < YUCK_MAX_POSARGS; i++) { op = argv[[i]]; switch (*op) { case '-': /* could be an option */ switch (*++op) { default: /* could be glued into one */ for (; *op; op++) { yield(shortopt, *op); } break; case '-': if (*++op == '\0') { i++; yield(dashdash); break; } yield(longopt, op); break; case '\0': goto plain_dash; } break; default: plain_dash: yield(arg, op); break; } } if (i < argc) { op = argv[[i]]; if (*op++ == '-' && *op++ == '-' && !*op) { /* another dashdash, filter out */ i++; } } /* has to be here as the max_pargs condition might drive us here */ coroutine(dashdash) { /* dashdash loop, pile everything on tgt->args * don't check for subcommands either, this is in accordance to * the git tool which won't accept commands after -- */ for (; i < argc; i++) { tgt->args[[tgt->nargs++]] = argv[[i]]; } } return 0; coroutine(longopt) { /* split into option and arg part */ char *arg; if ((arg = strchr(op, '=')) != NULL) { /* \nul this one out */ *arg++ = '\0'; } switch (tgt->cmd) { default: yield(yuck_cmd()[_longopt]); break; foreachq([__CMD], yuck_cmds(), [case yuck_cmd(defn([__CMD])): yield(yuck_cmd(defn([__CMD]))[_longopt]); break; ])} resume; dnl TYPE actions pushdef([yuck_flag_action], [tgt->yuck_slot([$1], [$2])++; goto xtra_chk])dnl pushdef([yuck_arg_action], [tgt->yuck_slot([$1], [$2]) = arg ?: argv[[++i]]])dnl pushdef([yuck_arg_opt_action], [tgt->yuck_slot([$1], [$2]) = arg ?: YUCK_OPTARG_NONE])dnl pushdef([yuck_arg_mul_action], [tgt->yuck_slot([$1], [$2]) = yuck_append( tgt->yuck_slot([$1], [$2]), tgt->yuck_cnt_slot([$1], [$2])++, arg ?: argv[[++i]]); if (tgt->yuck_slot([$1], [$2]) == NULL) { return -1; }])dnl pushdef([yuck_arg_mul_opt_action], [tgt->yuck_slot([$1], [$2]) = yuck_append( tgt->yuck_slot([$1], [$2]), tgt->yuck_cnt_slot([$1], [$2])++, arg ?: YUCK_OPTARG_NONE); if (tgt->yuck_slot([$1], [$2]) == NULL) { return -1; }])dnl pushdef([yuck_auto_action], [/* invoke auto action and exit */ yuck_auto_[]yuck_canon([$1], [$2])(tgt); resume_at(success)])dnl foreachq([__CMD], yuck_umbcmds(), [coroutine(yuck_cmd(defn([__CMD]))[_longopt]) { if (0) { ; }dnl foreachq([__IDN], yuck_idents(defn([__CMD])), [ dnl pushdef([long], yuck_long(defn([__IDN]), defn([__CMD])))[]dnl ifelse(defn([long]), [], [divert(-1)])dnl else if (yuck_streqp(op, "defn([long])")) { popdef([long])[]dnl dnl now simply expand yuck_foo_action: yuck_option_action(defn([__IDN]), defn([__CMD])); }dnl divert[]dnl ]) else { ifelse(defn([__CMD]), [], [dnl ifdef([YOPT_ALLOW_UNKNOWN_DASHDASH], [dnl /* just treat it as argument then */ resume_at(arg); ], [dnl /* grml */ fprintf(stderr, "YUCK_UMB_STR: unrecognized option `--%s'\n", op); resume_at(failure); xtra_chk: if (arg != NULL) { fprintf(stderr, "YUCK_UMB_STR: option `--%s' doesn't allow an argument\n", op); resume_at(failure); } ])dnl ], [dnl resume_at(yuck_cmd()[_longopt]); ])dnl } if (i >= argc) { fprintf(stderr, "YUCK_UMB_STR: option `--%s' requires an argument\n", op); resume_at(failure); } resume; } ]) popdef([yuck_flag_action])dnl popdef([yuck_arg_action])dnl popdef([yuck_arg_mul_action])dnl popdef([yuck_arg_opt_action])dnl popdef([yuck_arg_mul_opt_action])dnl popdef([yuck_auto_action])dnl } coroutine(shortopt) { char *arg = op + 1U; switch (tgt->cmd) { default: yield(yuck_cmd()[_shortopt]); break; foreachq([__CMD], yuck_cmds(), [case yuck_cmd(defn([__CMD])): yield(yuck_cmd(defn([__CMD]))[_shortopt]); break; ])} resume; dnl TYPE actions pushdef([yuck_flag_action], [tgt->yuck_slot([$1], [$2])++])dnl pushdef([yuck_arg_action], [tgt->yuck_slot([$1], [$2]) = *arg ? (op += strlen(arg), arg) : argv[[++i]]])dnl pushdef([yuck_arg_opt_action], [tgt->yuck_slot([$1], [$2]) = *arg ? (op += strlen(arg), arg) : YUCK_OPTARG_NONE])dnl pushdef([yuck_arg_mul_action], [tgt->yuck_slot([$1], [$2]) = yuck_append( tgt->yuck_slot([$1], [$2]), tgt->yuck_cnt_slot([$1], [$2])++, *arg ? (op += strlen(arg), arg) : argv[[++i]]); if (tgt->yuck_slot([$1], [$2]) == NULL) { return -1; }])dnl pushdef([yuck_arg_mul_opt_action], [tgt->yuck_slot([$1], [$2]) = yuck_append( tgt->yuck_slot([$1], [$2]), tgt->yuck_cnt_slot([$1], [$2])++, *arg ? (op += strlen(arg), arg) : YUCK_OPTARG_NONE); if (tgt->yuck_slot([$1], [$2]) == NULL) { return -1; }])dnl pushdef([yuck_auto_action], [/* invoke auto action and exit */ yuck_auto_[]yuck_canon([$1], [$2])(tgt); resume_at(success)])dnl foreachq([__CMD], yuck_umbcmds(), [coroutine(yuck_cmd(defn([__CMD]))[_shortopt]) { switch (*op) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (op[[-1]] == '-') { /* literal treatment of numeral */ resume_at(arg); } /*@fallthrough@*/ default: divert(1); ifdef([YOPT_ALLOW_UNKNOWN_DASH], [dnl resume_at(arg); ], [dnl fprintf(stderr, "YUCK_UMB_STR: invalid option -%c\n", *op); resume_at(failure); ])dnl ifdef([YUCK_SHORTS_HAVE_NUMERALS], [ /* [yuck_shorts()] (= yuck_shorts()) * has numerals as shortopts * don't allow literal treatment of numerals */divert(-1)]) divert(2); resume_at(yuck_cmd()[_shortopt]); divert(0); ifelse(defn([__CMD]), [], [select_divert(1)], [select_divert(2)])dnl divert[]dnl foreachq([__IDN], yuck_idents(defn([__CMD])), [dnl pushdef([short], yuck_short(defn([__IDN]), defn([__CMD])))dnl ifelse(defn([short]), [], [divert(-1)])dnl case 'defn([short])': popdef([short])dnl dnl dnl now simply expand yuck_foo_action: yuck_option_action(defn([__IDN]), defn([__CMD])); break; divert[]dnl ])dnl } if (i >= argc) { fprintf(stderr, "YUCK_UMB_STR: option `--%s' requires an argument\n", op); resume_at(failure); } resume; } ]) popdef([yuck_flag_action])dnl popdef([yuck_arg_action])dnl popdef([yuck_arg_opt_action])dnl popdef([yuck_arg_mul_action])dnl popdef([yuck_arg_mul_opt_action])dnl popdef([yuck_auto_action])dnl } coroutine(arg) { if (tgt->cmd || YUCK_NCMDS == 0U) { tgt->args[[tgt->nargs++]] = argv[[i]]; } else { /* ah, might be an arg then */ if ((tgt->cmd = yuck_parse_cmd(op)) > YUCK_NCMDS) { return -1; } } resume; } coroutine(failure) { exit(EXIT_FAILURE); } coroutine(success) { exit(EXIT_SUCCESS); } } DEFUN void yuck_free(yuck_t tgt[[static 1U]]) { if (tgt->args != NULL) { /* free despite const qualifier */ free(tgt->args); } /* free mulargs */ switch (tgt->cmd) { void *ptr; default: break; pushdef([action], [dnl ptr = tgt->yuck_slot([$1], [$2]); if (ptr != NULL) { free(ptr); } ])dnl dnl TYPE actions pushdef([yuck_flag_action], [])dnl pushdef([yuck_arg_action], [])dnl pushdef([yuck_arg_opt_action], [])dnl pushdef([yuck_arg_mul_action], defn([action]))dnl pushdef([yuck_arg_mul_opt_action], defn([action]))dnl pushdef([yuck_auto_action], [])dnl foreachq([__CMD], yuck_umbcmds(), [dnl case yuck_cmd(defn([__CMD])): foreachq([__IDN], yuck_idents(defn([__CMD])), [dnl yuck_option_action(defn([__IDN]), defn([__CMD])); ])[]dnl break; ])[]dnl popdef([action])dnl popdef([yuck_flag_action])dnl popdef([yuck_arg_action])dnl popdef([yuck_arg_opt_action])dnl popdef([yuck_arg_mul_action])dnl popdef([yuck_arg_mul_opt_action])dnl popdef([yuck_auto_opt_action])dnl } return; } DEFUN void yuck_auto_usage(const yuck_t src[[static 1U]]) { switch (src->cmd) { default: YUCK_NOCMD: puts("Usage: YUCK_UMB_STR [[OPTION]]...dnl ifelse(yuck_cmds(), [], [], [ COMMAND])[]dnl ifelse(defn([YUCK_UMB_POSARG]), [], [], [ defn([YUCK_UMB_POSARG])])\n\ ifelse(yuck_umb_desc(), [], [], [dnl \n\ yuck_C_literal(yuck_umb_desc())\n\ ])dnl "); break; foreachq([__CMD], yuck_cmds(), [ case yuck_cmd(defn([__CMD])): puts("Usage: YUCK_UMB_STR dnl yuck_cmd_string(defn([__CMD]))[]dnl ifelse(yuck_idents(defn([__CMD])), [], [], [ [[OPTION]]...])[]dnl ifelse(yuck_cmd_posarg(defn([__CMD])), [], [], [ yuck_cmd_posarg(defn([__CMD]))])\n\ ifelse(yuck_cmd_desc(defn([__CMD])), [], [], [dnl \n\ yuck_C_literal(yuck_cmd_desc(defn([__CMD])))\n\ ])dnl "); break; ]) } #if defined yuck_post_usage yuck_post_usage(src); #endif /* yuck_post_usage */ return; } DEFUN void yuck_auto_help(const yuck_t src[[static 1U]]) { yuck_auto_usage(src); ifelse(yuck_cmds(), [], [], [dnl if (src->cmd == YUCK_NOCMD) { /* also output a list of commands */ puts("COMMAND may be one of:\n\ foreachq([__CMD], yuck_cmds(), [yuck_C_literal(yuck_cmd_line(defn([__CMD])))\n\ ])"); } ])dnl /* leave a not about common options */ if (src->cmd == YUCK_NOCMD) { ifelse(yuck_cmds(), [], [dnl ; ], [dnl puts("\ Options accepted by all commands:"); ])dnl ifelse(yuck_cmds(), [], [], [dnl } else { puts("\ Common options:\n\ foreachq([__IDN], yuck_idents([]), [dnl yuck_C_literal(backquote([yuck_option_help_line(defn([__IDN]), [])]))[]dnl ])dnl "); ])dnl } switch (src->cmd) { default:foreachq([__CMD], yuck_umbcmds(), [ case yuck_cmd(defn([__CMD])): puts("\ ifelse(defn([__CMD]), [], [], [dnl ifelse(yuck_idents(defn([__CMD])), [], [], [dnl Command-specific options:\n\ ])dnl ])dnl foreachq([__IDN], yuck_idents(defn([__CMD])), [dnl yuck_C_literal(backquote([yuck_option_help_line(defn([__IDN]), defn([__CMD]))]))[]dnl ])dnl "); break; ]) } #if defined yuck_post_help yuck_post_help(src); #endif /* yuck_post_help */ #if defined PACKAGE_BUGREPORT puts("\n\ Report bugs to " PACKAGE_BUGREPORT); #endif /* PACKAGE_BUGREPORT */ return; } DEFUN void yuck_auto_version(const yuck_t src[[static 1U]]) { switch (src->cmd) { default: ifdef([YUCK_VERSION], [dnl puts("YUCK_UMB_STR YUCK_VERSION"); ], [dnl #if 0 #elif defined package_string puts(package_string); #elif defined package_version printf("YUCK_UMB_STR %s\n", package_version); #elif defined PACKAGE_STRING puts(PACKAGE_STRING); #elif defined PACKAGE_VERSION puts("YUCK_UMB_STR " PACKAGE_VERSION); #elif defined VERSION puts("YUCK_UMB_STR " VERSION); #else /* !PACKAGE_VERSION, !VERSION */ puts("YUCK_UMB_STR unknown version"); #endif /* PACKAGE_VERSION */ ])dnl break; } #if defined yuck_post_version yuck_post_version(src); #endif /* yuck_post_version */ return; } popdef([DEFUN])dnl #if defined __INTEL_COMPILER # pragma warning (pop) #elif defined __GNUC__ # if __GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 6 # pragma GCC diagnostic pop # endif /* GCC version */ #endif /* __INTEL_COMPILER */ changequote`'dnl dateutils-0.4.5/build-aux/yuck-coru.h.m4000066400000000000000000000064731335042257000200340ustar00rootroot00000000000000/* -*- c -*- */ changequote`'changequote([,])dnl changecom([#])dnl #if !defined INCLUDED_yuck_h_ #define INCLUDED_yuck_h_ #include #define YUCK_OPTARG_NONE ((void*)0x1U) enum yuck_cmds_e { pushdef([last], yuck_cmd())pushdef([first], defn([last]))[]dnl /* value used when no command was specified */ first = 0U, /* actual commands */ foreachq([cmd], yuck_cmds(), [define([last], yuck_cmd(defn([cmd])))[]last, ]) /* convenience identifiers */ YUCK_NOCMD = first, YUCK_NCMDS = last popdef([last])popdef([first])[]dnl }; define([yuck_slot_predecl], [dnl yuck_iftype([$1], [$2], [arg,mul], [size_t ]yuck_canon([$1], [$2])[_nargs], [arg,mul,opt], [size_t ]yuck_canon([$1], [$2])[_nargs], )dnl ])dnl define([yuck_slot_decl], [dnl pushdef([pre], [yuck_slot_predecl([$1], [$2])])dnl pushdef([ident], [yuck_slot_identifier([$1], [$2])])dnl yuck_iftype([$1], [$2], [flag], [unsigned int ident;], [arg], [char *ident;], [arg,opt], [char *ident;], [arg,mul], [pre; char **ident;], [arg,mul,opt], [pre; char **ident;], [auto], [/* $1 is handled automatically */])dnl popdef([pre])dnl popdef([ident])dnl ])dnl ifelse(yuck_cmds(), [], [dnl typedef struct yuck_s yuck_t; ], [dnl typedef union yuck_u yuck_t; ])dnl foreachq([cmd], yuck_cmds(), [ /* convenience structure for `cmd' */ struct yuck_cmd_[]defn([cmd])[]_s { enum yuck_cmds_e [cmd]; /* left-over arguments, the command string is never a part of this */ size_t nargs; char **args; foreachq([slot], yuck_idents(), [ yuck_slot_decl(defn([slot]))[]dnl ]) foreachq([slot], yuck_idents(defn([cmd])), [ yuck_slot_decl(defn([slot]), defn([cmd]))[]dnl ]) }; ]) ifelse(yuck_cmds(), [], [dnl /* generic struct */ struct yuck_s { enum yuck_cmds_e cmd; /* left-over arguments, * the command string is never a part of this */ size_t nargs; char **args; /* slots common to all commands */ foreachq([slot], yuck_idents(), [ yuck_slot_decl(defn([slot]))[]dnl ]) }; ], [dnl else union yuck_u { /* generic struct */ struct { enum yuck_cmds_e cmd; /* left-over arguments, * the command string is never a part of this */ size_t nargs; char **args; /* slots common to all commands */ foreachq([slot], yuck_idents(), [dnl yuck_slot_decl(defn([slot])) ])dnl }; /* depending on CMD at most one of the following structs is filled in * if CMD is YUCK_NONE no slots of this union must be accessed */ foreachq([cmd], yuck_cmds(), [dnl struct yuck_cmd_[]defn([cmd])[]_s defn([cmd]); ])dnl }; ]) pushdef([DECLF], ifdef([YUCK_HEADER], [extern], [static]))[]dnl DECLF __attribute__((nonnull(1))) int yuck_parse(yuck_t*, int argc, char *argv[[]]); DECLF __attribute__((nonnull(1))) void yuck_free(yuck_t*); DECLF __attribute__((nonnull(1))) void yuck_auto_help(const yuck_t*); DECLF __attribute__((nonnull(1))) void yuck_auto_usage(const yuck_t*); DECLF __attribute__((nonnull(1))) void yuck_auto_version(const yuck_t*); /* some hooks */ #if defined yuck_post_help DECLF __attribute__((nonnull(1))) void yuck_post_help(const yuck_t*); #endif /* yuck_post_help */ #if defined yuck_post_usage DECLF __attribute__((nonnull(1))) void yuck_post_usage(const yuck_t*); #endif /* yuck_post_usage */ #if defined yuck_post_version DECLF __attribute__((nonnull(1))) void yuck_post_version(const yuck_t*); #endif /* yuck_post_version */ popdef([DECLF])[]dnl #endif /* INCLUDED_yuck_h_ */ changequote`'dnl dateutils-0.4.5/build-aux/yuck-scmver.c000066400000000000000000000523461335042257000200370ustar00rootroot00000000000000/*** yuck-scmver.c -- snarf versions off project cwds * * Copyright (C) 2013-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of yuck. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***/ #if defined HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #include #include #include #include #include #include "yuck-scmver.h" #if !defined LIKELY # define LIKELY(_x) __builtin_expect((_x), 1) #endif /* !LIKELY */ #if !defined UNLIKELY # define UNLIKELY(_x) __builtin_expect((_x), 0) #endif /* UNLIKELY */ #if !defined UNUSED # define UNUSED(_x) _x __attribute__((unused)) #endif /* !UNUSED */ #if !defined countof # define countof(x) (sizeof(x) / sizeof(*x)) #endif /* !countof */ #define _paste(x, y) x ## y #define paste(x, y) _paste(x, y) #if !defined with # define with(args...) \ for (args, *paste(__ep, __LINE__) = (void*)1; \ paste(__ep, __LINE__); paste(__ep, __LINE__) = 0) #endif /* !with */ #define DEBUG(args...) /* globals */ const char *const yscm_strs[] = { [YUCK_SCM_TARBALL] = "tarball", [YUCK_SCM_GIT] = "git", [YUCK_SCM_BZR] = "bzr", [YUCK_SCM_HG] = "hg", }; static __attribute__((format(printf, 1, 2))) void error(const char *fmt, ...) { va_list vap; va_start(vap, fmt); vfprintf(stderr, fmt, vap); va_end(vap); if (errno) { fputc(':', stderr); fputc(' ', stderr); fputs(strerror(errno), stderr); } fputc('\n', stderr); return; } static inline __attribute__((const, pure, always_inline)) char* deconst(const char *s) { union { const char *c; char *p; } x = {s}; return x.p; } static __attribute__((unused)) size_t xstrlcpy(char *restrict dst, const char *src, size_t dsz) { size_t ssz; if (UNLIKELY(dsz == 0U)) { return 0U; } if ((ssz = strlen(src)) > dsz) { ssz = dsz - 1U; } memcpy(dst, src, ssz); dst[ssz] = '\0'; return ssz; } static __attribute__((unused)) size_t xstrlncpy(char *restrict dst, size_t dsz, const char *src, size_t ssz) { if (UNLIKELY(dsz == 0U)) { return 0U; } if (ssz > dsz) { ssz = dsz - 1U; } memcpy(dst, src, ssz); dst[ssz] = '\0'; return ssz; } static char* xdirname(char *restrict fn, const char *fp) { /* find next dir in FN from FP backwards */ if (fp == NULL) { fp = fn + strlen(fn); } else if (fp <= fn) { return NULL; } for (--fp; fp >= fn && *fp != '/'; fp--); while (fp >= fn && *--fp == '/'); if (fp >= fn) { /* replace / by \nul and return pointer */ char *dp = fn + (++fp - fn); *dp = '\0'; return dp; } /* return \nul */ return NULL; } static char* xmemmem(const char *hay, const size_t hayz, const char *ndl, const size_t ndlz) { const char *const eoh = hay + hayz; const char *const eon = ndl + ndlz; const char *hp; const char *np; const char *cand; unsigned int hsum; unsigned int nsum; unsigned int eqp; /* trivial checks first * a 0-sized needle is defined to be found anywhere in haystack * then run strchr() to find a candidate in HAYSTACK (i.e. a portion * that happens to begin with *NEEDLE) */ if (ndlz == 0UL) { return deconst(hay); } else if ((hay = memchr(hay, *ndl, hayz)) == NULL) { /* trivial */ return NULL; } /* First characters of haystack and needle are the same now. Both are * guaranteed to be at least one character long. Now computes the sum * of characters values of needle together with the sum of the first * needle_len characters of haystack. */ for (hp = hay + 1U, np = ndl + 1U, hsum = *hay, nsum = *hay, eqp = 1U; hp < eoh && np < eon; hsum ^= *hp, nsum ^= *np, eqp &= *hp == *np, hp++, np++); /* HP now references the (NZ + 1)-th character. */ if (np < eon) { /* haystack is smaller than needle, :O */ return NULL; } else if (eqp) { /* found a match */ return deconst(hay); } /* now loop through the rest of haystack, * updating the sum iteratively */ for (cand = hay; hp < eoh; hp++) { hsum ^= *cand++; hsum ^= *hp; /* Since the sum of the characters is already known to be * equal at that point, it is enough to check just NZ - 1 * characters for equality, * also CAND is by design < HP, so no need for range checks */ if (hsum == nsum && memcmp(cand, ndl, ndlz - 1U) == 0) { return deconst(cand); } } return NULL; } static unsigned int hextou(const char *sp, char **ep) { register unsigned int res = 0U; size_t i; if (UNLIKELY(sp == NULL)) { goto out; } else if (*sp == '\0') { goto out; } for (i = 0U; i < sizeof(res) * 8U / 4U - 1U; sp++, i++) { register unsigned int this; switch (*sp) { case '0' ... '9': this = *sp - '0'; break; case 'a' ... 'f': this = *sp - 'a' + 10U; break; case 'A' ... 'F': this = *sp - 'A' + 10U; break; default: goto fucked; } res <<= 4U; res |= this; } fucked: res <<= 4U; res |= i; /* keep reading the hexstring as long as it lasts */ for (;; sp++) { switch (*sp) { case '0' ... '9': case 'a' ... 'f': case 'A' ... 'F': continue; default: goto out; } } out: if (ep != NULL) { *ep = (char*)1U + (sp - (char*)1U); } return res; } /* version snarfers */ static __attribute__((noinline)) pid_t run(int *fd, ...) { static char *cmdline[16U]; va_list vap; pid_t p; /* to snarf off traffic from the child */ int intfd[2]; va_start(vap, fd); for (size_t i = 0U; i < countof(cmdline) && (cmdline[i] = va_arg(vap, char*)) != NULL; i++); va_end(vap); assert(*cmdline); if (pipe(intfd) < 0) { error("pipe setup to/from %s failed", cmdline[0U]); return -1; } switch ((p = vfork())) { case -1: /* i am an error */ error("vfork for %s failed", cmdline[0U]); return -1; default: /* i am the parent */ close(intfd[1]); if (fd != NULL) { *fd = intfd[0]; } else { close(intfd[0]); } return p; case 0: /* i am the child */ break; } /* child code here */ close(intfd[0]); dup2(intfd[1], STDOUT_FILENO); execvp(cmdline[0U], cmdline); error("execvp(%s) failed", cmdline[0U]); _exit(EXIT_FAILURE); } static int fin(pid_t p) { int rc = 2; int st; while (waitpid(p, &st, 0) != p); if (WIFEXITED(st)) { rc = WEXITSTATUS(st); } return rc; } static yuck_scm_t find_scm(char *restrict fn, size_t fz, const char *path) { struct stat st[1U]; char *restrict dp = fn; /* make a copy so we can fiddle with it */ if (UNLIKELY(path == NULL)) { cwd: /* just use "." then */ *dp++ = '.'; *dp = '\0'; } else if ((dp += xstrlcpy(fn, path, fz)) == fn) { goto cwd; } again: if (stat(fn, st) < 0) { return YUCK_SCM_ERROR; } else if (UNLIKELY((size_t)(dp - fn) + 5U >= fz)) { /* not enough space */ return YUCK_SCM_ERROR; } else if (!S_ISDIR(st->st_mode)) { /* not a directory, get the dir bit and start over */ if ((dp = xdirname(fn, dp)) == NULL) { dp = fn; goto cwd; } goto again; } scm_chk: /* now check for .git, .bzr, .hg */ xstrlcpy(dp, "/.git", fz - (dp - fn)); DEBUG("trying %s ...\n", fn); if (stat(fn, st) == 0 && S_ISDIR(st->st_mode)) { /* yay it's a .git */ *dp = '\0'; return YUCK_SCM_GIT; } xstrlcpy(dp, "/.bzr", fz - (dp - fn)); DEBUG("trying %s ...\n", fn); if (stat(fn, st) == 0 && S_ISDIR(st->st_mode)) { /* yay it's a .git */ *dp = '\0'; return YUCK_SCM_BZR; } xstrlcpy(dp, "/.hg", fz - (dp - fn)); DEBUG("trying %s ...\n", fn); if (stat(fn, st) == 0 && S_ISDIR(st->st_mode)) { /* yay it's a .git */ *dp = '\0'; return YUCK_SCM_HG; } /* nothing then, traverse upwards */ if (*fn != '/') { /* make sure we don't go up indefinitely * comparing the current inode to ./.. */ with (ino_t curino) { *dp = '\0'; if (stat(fn, st) < 0) { return YUCK_SCM_ERROR; } /* memorise inode */ curino = st->st_ino; /* go upwards by appending /.. */ dp += xstrlcpy(dp, "/..", fz - (dp - fn)); /* check inode again */ if (stat(fn, st) < 0) { return YUCK_SCM_ERROR; } else if (st->st_ino == curino) { break; } goto scm_chk; } } else if ((dp = xdirname(fn, dp)) != NULL) { goto scm_chk; } return YUCK_SCM_TARBALL; } static int rd_version(struct yuck_version_s *restrict v, const char *buf, size_t bsz) { /* reads a normalised version string vX.Y.Z-DIST-SCM RVSN[-dirty] */ static const char dflag[] = "dirty"; const char *vtag = NULL; const char *eov; const char *dist = NULL; const char *eod; const char *bp = buf; const char *const ep = buf + bsz; /* parse buf */ switch (*bp) { case 'v': case 'V': bp++; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': break; default: /* weird, we req'd v-tags */ return -1; } if ((eov = memchr(vtag = bp, '-', ep - bp)) == NULL) { /* last field */ eov = ep; } else { dist = eov + 1U; } /* just for the fun of it, look for .git, .hg and .bzr as well */ with (const char *altp) { if ((altp = xmemmem(vtag, ep - vtag, ".git", 4U))) { v->scm = YUCK_SCM_GIT; eov = altp; dist = altp + 4U; } else if ((altp = xmemmem(vtag, ep - vtag, ".bzr", 4U))) { /* oooh looks like the alternative version * vX.Y.Z.gitDD.HASH */ v->scm = YUCK_SCM_BZR; eov = altp; dist = altp + 4U; } else if ((altp = xmemmem(vtag, ep - vtag, ".hg", 3U))) { /* oooh looks like the alternative version * vX.Y.Z.hgDD.HASH */ v->scm = YUCK_SCM_HG; eov = altp; dist = altp + 3U; } } /* bang vtag */ xstrlncpy(v->vtag, sizeof(v->vtag), vtag, eov - vtag); /* snarf distance */ if (dist == NULL) { return 0; } /* read distance */ with (char *on) { v->dist = strtoul(dist, &on, 10); eod = on; } switch (*eod) { default: case '\0': return 0; case '.': if (v->scm <= YUCK_SCM_TARBALL) { /* huh? */ return -1; } /*@fallthrough@*/ case '-': /* the show is going on, like it must */ bp = eod + 1U; break; } switch (*bp++) { case 'g': /* git repo */ v->scm = YUCK_SCM_GIT; break; case 'h': /* hg repo */ v->scm = YUCK_SCM_HG; break; case 'b': if (v->scm <= YUCK_SCM_TARBALL) { v->scm = YUCK_SCM_BZR; break; } /* else probably git or hg hash starting with b */ /*@fallthrough@*/ default: /* could have been set already then */ if (v->scm > YUCK_SCM_TARBALL) { /* rewind bp and continue */ bp--; break; } /* otherwise we simply don't know */ return 0; } /* read scm revision */ with (char *on) { v->rvsn = hextou(bp, &on); bp = on; } if (bp >= ep) { ; } else if (*bp != '-' && *bp != '.') { ; } else if (bp + sizeof(dflag) > ep) { /* too short to fit `dirty' */ ; } else if (!memcmp(++bp, dflag, sizeof(dflag) - 1U)) { v->dirty = 1U; } return 0; } static ssize_t wr_version(char *restrict buf, size_t bsz, const struct yuck_version_s *v) { static const char yscm_abbr[] = "tgbh"; const char *const ep = buf + bsz; char *bp = buf; if (UNLIKELY(buf == NULL || bsz == 0U)) { return -1; } *bp++ = 'v'; bp += xstrlcpy(bp, v->vtag, ep - bp); if (!v->dist) { goto out; } else if (bp + 1U >= ep) { /* not enough space */ return -1; } /* get the dist bit on the wire */ *bp++ = '-'; bp += snprintf(bp, ep - bp, "%u", v->dist); if (!v->rvsn || v->scm <= YUCK_SCM_TARBALL) { goto out; } else if (bp + 2U + 8U >= ep) { /* not enough space */ return -1; } *bp++ = '-'; *bp++ = yscm_abbr[v->scm]; bp += snprintf(bp, ep - bp, "%0*x", (int)(v->rvsn & 0x07U), v->rvsn >> 4U); if (!v->dirty) { goto out; } else if (bp + 1U + 5U >= ep) { /* not enough space */ return -1; } bp += xstrlcpy(bp, "-dirty", ep - bp); out: return bp - buf; } static int git_version(struct yuck_version_s v[static 1U]) { pid_t chld; int fd[1U]; int rc = 0; if ((chld = run(fd, "git", "describe", "--tags", "--match=v[0-9]*", "--abbrev=8", "--dirty", NULL)) < 0) { return -1; } /* shouldn't be heaps, so just use a single read */ with (char buf[256U]) { const char *vtag; const char *dist; char *bp; ssize_t nrd; if ((nrd = read(*fd, buf, sizeof(buf))) <= 0) { /* no version then aye */ rc = -1; break; } buf[nrd - 1U/* for \n*/] = '\0'; /* parse buf */ bp = buf; if (*bp++ != 'v') { /* weird, we req'd v-tags though */ rc = -1; break; } else if ((bp = strchr(vtag = bp, '-')) != NULL) { /* tokenise sting */ *bp++ = '\0'; } /* bang vtag */ xstrlcpy(v->vtag, vtag, sizeof(v->vtag)); /* snarf distance */ if (bp == NULL) { break; } else if ((bp = strchr(dist = bp, '-')) != NULL) { /* tokenize */ *bp++ = '\0'; } /* read distance */ v->dist = strtoul(dist, &bp, 10); if (*++bp == 'g') { bp++; /* read scm revision */ v->rvsn = hextou(bp, &bp); } if (*bp == '\0') { break; } else if (*bp == '-') { bp++; } if (!strcmp(bp, "dirty")) { v->dirty = 1U; } } close(*fd); if (fin(chld) != 0) { rc = -1; } return rc; } static int hg_version(struct yuck_version_s v[static 1U]) { pid_t chld; int fd[1U]; int rc = 0; if ((chld = run(fd, "hg", "log", "--rev", ".", "--template", "{latesttag}\t{latesttagdistance}\t{node|short}\n", NULL)) < 0) { return -1; } /* shouldn't be heaps, so just use a single read */ with (char buf[256U]) { const char *vtag; const char *dist; char *bp; ssize_t nrd; if ((nrd = read(*fd, buf, sizeof(buf))) <= 0) { /* no version then aye */ rc = -1; break; } buf[nrd - 1U/* for \n*/] = '\0'; /* parse buf */ bp = buf; if (*bp++ != 'v') { /* technically we could request the latest v-tag * but i'm no hg buff so fuck it */ rc = -1; break; } else if ((bp = strchr(vtag = bp, '\t')) != NULL) { /* tokenise */ *bp++ = '\0'; } /* bang vtag */ xstrlcpy(v->vtag, vtag, sizeof(v->vtag)); if (UNLIKELY(bp == NULL)) { /* huh? */ rc = -1; break; } else if ((bp = strchr(dist = bp, '\t')) != NULL) { /* tokenise */ *bp++ = '\0'; } /* bang distance */ v->dist = strtoul(dist, NULL, 10); /* bang revision */ v->rvsn = hextou(bp, NULL); } close(*fd); if (fin(chld) != 0) { rc = -1; } return rc; } static int bzr_version(struct yuck_version_s v[static 1U]) { pid_t chld; int fd[1U]; int rc = 0; /* first get current revision number */ if ((chld = run(fd, "bzr", "revno", NULL)) < 0) { return -1; } /* shouldn't be heaps, so just use a single read */ with (char buf[256U]) { ssize_t nrd; if ((nrd = read(*fd, buf, sizeof(buf))) <= 0) { /* no version then aye */ break; } with (char *on) { v->rvsn = strtoul(buf, &on, 10); if (LIKELY(on != NULL)) { v->rvsn <<= 4U; v->rvsn |= on - buf; } } } close(*fd); if (fin(chld) != 0) { return -1; } if ((chld = run(fd, "bzr", "tags", "--sort=time", NULL)) < 0) { return -1; } /* could be a lot, we only need the last line though */ with (char buf[4096U]) { const char *vtag; size_t bz; char *bp; ssize_t nrd; bp = buf; bz = sizeof(buf); while ((nrd = read(*fd, bp, bz)) == (ssize_t)bz) { /* find last line */ while (bz-- > 0 && buf[bz] != '\n'); /* reassess bz */ bz++; /* reassess bp */ bp = buf + (sizeof(buf) - bz); if (LIKELY(bz < sizeof(buf))) { memmove(buf, buf + bz, sizeof(buf) - bz); } } if (nrd <= 0) { /* no version then aye */ break; } bp[nrd - 1U/* for \n*/] = '\0'; /* find last line */ bp += nrd; while (--bp >= buf && *bp != '\n'); /* parse buf */ if (*++bp != 'v') { /* we want v tags, we could go back and see if * there are any */ rc = -1; break; } else if ((bp = strchr(vtag = ++bp, ' ')) != NULL) { /* tokenise */ *bp++ = '\0'; } /* bang vtag */ xstrlcpy(v->vtag, vtag, sizeof(v->vtag)); if (bp == NULL) { break; } /* read over all the whitespace to find the tag's revno */ with (unsigned int rno = strtoul(bp, NULL, 10)) { v->dist = v->rvsn - rno; } } close(*fd); if (fin(chld) != 0) { rc = -1; } return rc; } /* public api */ #if !defined PATH_MAX # define PATH_MAX (256U) #endif /* !PATH_MAX */ int yuck_version(struct yuck_version_s *restrict v, const char *path) { char cwd[PATH_MAX]; char fn[PATH_MAX]; int rc = -1; /* initialise result structure */ memset(v, 0, sizeof(*v)); if (getcwd(cwd, sizeof(cwd)) == NULL) { return -1; } switch ((v->scm = find_scm(fn, sizeof(fn), path))) { case YUCK_SCM_ERROR: case YUCK_SCM_TARBALL: default: /* can't determine version numbers in tarball, can we? */ return -1; case YUCK_SCM_GIT: case YUCK_SCM_BZR: case YUCK_SCM_HG: if (chdir(fn) < 0) { break; } switch (v->scm) { case YUCK_SCM_GIT: rc = git_version(v); break; case YUCK_SCM_BZR: rc = bzr_version(v); break; case YUCK_SCM_HG: rc = hg_version(v); break; default: break; } if (chdir(cwd) < 0) { /* oh big cluster fuck */ rc = -1; } break; } return rc; } int yuck_version_read(struct yuck_version_s *restrict ref, const char *fn) { int rc = 0; int fd; /* initialise result structure */ memset(ref, 0, sizeof(*ref)); if (fn[0U] == '-' && fn[1U] == '\0') { fd = STDIN_FILENO; } else if ((fd = open(fn, O_RDONLY)) < 0) { return -1; } /* otherwise read and parse the string */ with (char buf[256U]) { ssize_t nrd; char *bp; if ((nrd = read(fd, buf, sizeof(buf))) <= 0) { /* no version then aye */ rc = -1; break; } else if ((bp = memchr(buf, '\n', nrd)) != NULL) { /* just go with the first line */ *bp = '\0'; nrd = bp - buf; } else if ((size_t)nrd < sizeof(buf)) { /* finalise with \nul */ buf[nrd] = '\0'; } else { /* finalise with \nul, cutting off the last byte */ buf[--nrd] = '\0'; } /* otherwise just read him */ rc = rd_version(ref, buf, nrd); } close(fd); return rc; } ssize_t yuck_version_write_fd(int fd, const struct yuck_version_s *ref) { char buf[256U]; ssize_t nwr; if ((nwr = wr_version(buf, sizeof(buf), ref)) <= 0) { return -1; } /* otherwise write */ buf[nwr++] = '\n'; return write(fd, buf, nwr); } int yuck_version_write(const char *fn, const struct yuck_version_s *ref) { int rc = 0; int fd; if (fn[0U] == '-' && fn[1U] == '\0') { fd = STDOUT_FILENO; } else if ((fd = open(fn, O_RDWR | O_CREAT | O_TRUNC, 0666)) < 0) { return -1; } if (yuck_version_write_fd(fd, ref) < 0) { rc = -1; } close(fd); return rc; } int yuck_version_cmp(yuck_version_t v1, yuck_version_t v2) { if (v1->dist == 0U && v2->dist == 0U) { /* must be a tag then, innit? */ return memcmp(v1->vtag, v2->vtag, sizeof(v1->vtag)); } /* just brute force the comparison, consider -dirty > -clean */ return memcmp(v1, v2, sizeof(*v1)); } #if defined BOOTSTRAP int main(int argc, char *argv[]) { /* usage would be yuck-scmver SCMDIR [REFERENCE] */ static struct yuck_version_s v[1U]; int rc = 0; /* prefer reference file */ if (argc > 2 && (rc = yuck_version_read(v, argv[2U])) == 0) { /* just use this one */ ; } else { rc = yuck_version(v, argv[1U]); } if (rc == 0) { fputs("define(YUCK_SCMVER_VERSION, ", stdout); fputs(v->vtag, stdout); if (v->scm > YUCK_SCM_TARBALL && v->dist) { fputc('.', stdout); fputs(yscm_strs[v->scm], stdout); fprintf(stdout, "%u.%0*x", v->dist, (int)(v->rvsn & 0x07U), v->rvsn >> 4U); } if (v->dirty) { fputs(".dirty", stdout); } fputs(")\n", stdout); } return -rc; } #endif /* BOOTSTRAP */ #if defined CONFIGURE int main(int argc, char *argv[]) { /* usage would be yuck-scmver [REFERENCE] */ static struct yuck_version_s v[1U]; int rc = 0; if (argc > 1) { rc = yuck_version_read(v, argv[1U]); #if defined VERSION_FILE } else if ((rc = yuck_version_read(v, VERSION_FILE)) == 0) { ; #endif /* VERSION_FILE */ } else { rc = yuck_version(v, NULL); } /* print if successful */ if (rc == 0) { fputs(v->vtag, stdout); if (v->scm > YUCK_SCM_TARBALL && v->dist) { fputc('.', stdout); fputs(yscm_strs[v->scm], stdout); fprintf(stdout, "%u.%0*x", v->dist, (int)(v->rvsn & 0x07U), v->rvsn >> 4U); } if (v->dirty) { fputs(".dirty", stdout); } fputc('\n', stdout); } return -rc; } #endif /* CONFIGURE */ /* yuck-scmver.c ends here */ dateutils-0.4.5/build-aux/yuck-scmver.h000066400000000000000000000056471335042257000200460ustar00rootroot00000000000000/*** yuck-version.h -- snarf versions off project cwds * * Copyright (C) 2013-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of yuck. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***/ #if !defined INCLUDED_yuck_version_h_ #define INCLUDED_yuck_version_h_ #include "stdlib.h" typedef const struct yuck_version_s *yuck_version_t; typedef enum { YUCK_SCM_ERROR = -1, YUCK_SCM_TARBALL, YUCK_SCM_GIT, YUCK_SCM_BZR, YUCK_SCM_HG, } yuck_scm_t; struct yuck_version_s { yuck_scm_t scm; unsigned int dirty:1U; char vtag[16U]; unsigned int dist; /* up to 28bits of revision id (hash for git), * the lower 4bits denote the length */ unsigned int rvsn; }; extern const char *const yscm_strs[]; /* public api */ /** * Determine SCM version of file(s) in PATH. */ extern int yuck_version(struct yuck_version_s *restrict v, const char *path); /** * Read a reference file FN and return scm version information. */ extern int yuck_version_read(struct yuck_version_s *restrict, const char *fn); /** * Write scm version information in V to reference file FN. */ extern int yuck_version_write(const char *fn, const struct yuck_version_s *v); /** * Write scm version into buffer. */ extern ssize_t yuck_version_write_fd(int fd, const struct yuck_version_s *v); /** * Compare two version objects, return <0 if V1 < V2, >0 if V1 > V2 and * 0 if V1 and V2 are considered equal. */ extern int yuck_version_cmp(yuck_version_t v1, yuck_version_t v2); #endif /* INCLUDED_yuck_version_h_ */ dateutils-0.4.5/build-aux/yuck-scmver.m4000066400000000000000000000004241335042257000201230ustar00rootroot00000000000000changequote`'changequote([,])dnl divert([-1]) changecom([##]) ## we used to define YUCK_SCMVER_VERSION in m4 terms here ## however in C it's so much easier to come by with the same thing ## so we reserve this file for future (m4-based) goodness divert[]dnl changequote()dnl dateutils-0.4.5/build-aux/yuck.am000066400000000000000000000020471335042257000167060ustar00rootroot00000000000000## automake rules for yuck ## set the following variables in the including Makefile.am beforehand ## noinst_PROGRAMS ## BUILT_SOURCES ## EXTRA_DIST ## DISTCLEANFILES yuck_CPPFLAGS = -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -D_BSD_SOURCE yuck_CPPFLAGS += -D_ALL_SOURCE yuck_CPPFLAGS += -D_DARWIN_C_SOURCE yuck_CPPFLAGS += -D_NETBSD_SOURCE noinst_PROGRAMS += yuck-bootstrap yuck_bootstrap_SOURCES = yuck.c yuck_bootstrap_CPPFLAGS = $(yuck_CPPFLAGS) yuck_bootstrap_CPPFLAGS += -DBOOTSTRAP yuck_bootstrap_CPPFLAGS += -DWITH_SCMVER noinst_PROGRAMS += yuck yuck_SOURCES = yuck.c yuck.yuck yuck_SOURCES += yuck-scmver.c yuck-scmver.h yuck-scmver.m4 yuck_SOURCES += yuck.m4 yuck_SOURCES += yuck-coru.c.m4 yuck-coru.h.m4 yuck_SOURCES += yuck.man.m4 yuck_CPPFLAGS += -DYUCK_TEMPLATE_PATH='"$(abs_srcdir)"' yuck_CPPFLAGS += -DWITH_SCMVER BUILT_SOURCES += yuck.yucc ## aix make wants all prereq's to exist EXTRA_DIST += yuck.m4i EXTRA_DIST += yuck.yucc DISTCLEANFILES += yuck.m4i yuck.yucc ## also include custom Makefile recipes include $(srcdir)/yuck.mk dateutils-0.4.5/build-aux/yuck.c000066400000000000000000001302661335042257000165400ustar00rootroot00000000000000/*** yuck.c -- generate umbrella commands * * Copyright (C) 2013-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of yuck. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***/ #if defined HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ /* for fgetln() */ #if !defined __BSD_VISIBLE # define __BSD_VISIBLE 1 #endif /* !__BSD_VISIBLE */ #if !defined _NETBSD_SOURCE # define _NETBSD_SOURCE #endif /* !_NETBSD_SOURCE */ #if !defined _DARWIN_SOURCE # define _DARWIN_SOURCE #endif /* !_DARWIN_SOURCE */ #if !defined _ALL_SOURCE # define _ALL_SOURCE #endif /* !_ALL_SOURCE */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined WITH_SCMVER # include #endif /* WITH_SCMVER */ #if !defined LIKELY # define LIKELY(_x) __builtin_expect((_x), 1) #endif /* !LIKELY */ #if !defined UNLIKELY # define UNLIKELY(_x) __builtin_expect((_x), 0) #endif /* UNLIKELY */ #if !defined UNUSED # define UNUSED(_x) _x __attribute__((unused)) #endif /* !UNUSED */ #if !defined countof # define countof(x) (sizeof(x) / sizeof(*x)) #endif /* !countof */ #if !defined strlenof # define strlenof(x) (sizeof(x) - 1ULL) #endif /* !strlenof */ #define _paste(x, y) x ## y #define paste(x, y) _paste(x, y) #if !defined with # define with(args...) \ for (args, *paste(__ep, __LINE__) = (void*)1; \ paste(__ep, __LINE__); paste(__ep, __LINE__) = 0) #endif /* !with */ #if !defined HAVE_GETLINE && !defined HAVE_FGETLN /* as a service to people including this file in their project * but who might not necessarily run the corresponding AC_CHECK_FUNS * we assume that a getline() is available. */ # define HAVE_GETLINE 1 #endif /* !HAVE_GETLINE && !HAVE_FGETLN */ typedef enum { YOPT_NONE, YOPT_ALLOW_UNKNOWN_DASH, YOPT_ALLOW_UNKNOWN_DASHDASH, } yopt_t; struct usg_s { char *umb; char *cmd; char *parg; char *desc; }; struct opt_s { char sopt; char *lopt; char *larg; char *desc; unsigned int oarg:1U; unsigned int marg:1U; }; #if !defined BOOTSTRAP && !defined WITH_SCMVER /* just forward declare this type so function signatures will work */ struct yuck_version_s; #endif /* WITH_SCMVER */ static __attribute__((format(printf, 1, 2))) void error(const char *fmt, ...) { va_list vap; va_start(vap, fmt); vfprintf(stderr, fmt, vap); va_end(vap); if (errno) { fputs(": ", stderr); fputs(strerror(errno), stderr); } fputc('\n', stderr); return; } static inline __attribute__((always_inline)) unsigned int yfls(unsigned int x) { return x ? sizeof(x) * 8U - __builtin_clz(x) : 0U; } static inline __attribute__((always_inline)) size_t max_zu(size_t x, size_t y) { return x > y ? x : y; } static size_t xstrncpy(char *restrict dst, const char *src, size_t ssz) { if (UNLIKELY(dst == NULL)) { return 0U; } memcpy(dst, src, ssz); dst[ssz] = '\0'; return ssz; } static __attribute__((unused)) size_t xstrlcpy(char *restrict dst, const char *src, size_t dsz) { size_t ssz = strlen(src); if (ssz > dsz) { ssz = dsz - 1U; } memcpy(dst, src, ssz); dst[ssz] = '\0'; return ssz; } static __attribute__((unused)) size_t xstrlncpy(char *restrict dst, size_t dsz, const char *src, size_t ssz) { if (ssz > dsz) { ssz = dsz - 1U; } memcpy(dst, src, ssz); dst[ssz] = '\0'; return ssz; } static __attribute__((unused)) bool xstreqp(const char *s1, const char *s2) { if (s1 == NULL && s2 == NULL) { return true; } else if (s1 == NULL || s2 == NULL) { /* one of them isn't NULL */ return false; } /* resort to normal strcmp */ return !strcasecmp(s1, s2); } static bool only_whitespace_p(const char *line, size_t llen) { for (const char *lp = line, *const ep = line + llen; lp < ep; lp++) { if (!isspace(*lp)) { return false; } } return true; } static bool isdashdash(const char c) { switch (c) { default: return true; case '=': case '[': case ']': case '.': case '\0' ... ' ': return false; } } static void massage_desc(char *str) { /* kick final newline and escape m4 quoting characters */ char *sp; for (sp = str; *sp; sp++) { switch (*sp) { default: break; case '[': /* map to STX (start of text) */ *sp = '\002'; break; case ']': /* map to ETX (end of text) */ *sp = '\003'; break; case '(': /* map to SO (shift out) */ *sp = '\016'; break; case ')': /* map to SI (shift in) */ *sp = '\017'; break; } } if (sp > str && sp[-1] == '\n') { *--sp = '\0'; } return; } #if !defined BOOTSTRAP static void unmassage_buf(char *restrict buf, size_t bsz) { /* turn m4 quoting character substitutes into brackets again */ for (char *restrict sp = buf, *const ep = buf + bsz; sp < ep; sp++) { switch (*sp) { default: break; case '\002': /* unmap STX (start of text) */ *sp = '['; break; case '\003': /* unmap ETX (end of text) */ *sp = ']'; break; case '\016': /* unmap SO (shift out) */ *sp = '('; break; case '\017': /* unmap SI (shift in) */ *sp = ')'; break; } } return; } static int mktempp(char *restrict tmpl[static 1U], int prefixlen) { static mode_t umsk; char *bp = *tmpl + prefixlen; char *const ep = *tmpl + strlen(*tmpl); mode_t m; int fd; if (UNLIKELY(!umsk)) { umsk = umask(0022); } if (ep[-6] != 'X' || ep[-5] != 'X' || ep[-4] != 'X' || ep[-3] != 'X' || ep[-2] != 'X' || ep[-1] != 'X') { if ((fd = open(bp, O_RDWR | O_CREAT | O_EXCL, 0666)) < 0 && (bp -= prefixlen, fd = open(bp, O_RDWR | O_CREAT | O_EXCL, 0666)) < 0) { /* fuck that then */ return -1; } } else if (m = umask(S_IXUSR | S_IRWXG | S_IRWXO), UNLIKELY((fd = mkstemp(bp), umask(m), fd < 0)) && UNLIKELY((bp -= prefixlen, /* reset to XXXXXX */ memset(ep - 6, 'X', 6U), fd = mkstemp(bp)) < 0)) { /* at least we tried */ return -1; } /* store result */ *tmpl = bp; return fd; } static FILE* mkftempp(char *restrict tmpl[static 1U], int prefixlen) { int fd; if (UNLIKELY((fd = mktempp(tmpl, prefixlen)) < 0)) { return NULL; } return fdopen(fd, "w"); } # if defined WITH_SCMVER static bool regfilep(const char *fn) { struct stat st[1U]; return stat(fn, st) == 0 && S_ISREG(st->st_mode); } # endif /* WITH_SCMVER */ #endif /* !BOOTSTRAP */ /* bang buffers */ typedef struct { /* the actual buffer (resizable) */ char *s; /* current size */ size_t n; /* current alloc size */ size_t z; } bbuf_t; static __attribute__((nonnull(1, 2))) char* bbuf_cat(bbuf_t *restrict b, const char *str, size_t ssz) { if (UNLIKELY(b->n + ssz + 1U/*\nul*/ > b->z)) { const size_t nu = max_zu(yfls(b->n + ssz + 1U) + 1U, 6U); char *tmp; tmp = realloc(b->s, (b->z = (1ULL << nu) * sizeof(*b->s))); if (UNLIKELY(tmp == NULL)) { goto free; } /* all's good then? */ b->s = tmp; } xstrncpy(b->s + b->n, str, ssz); b->n += ssz; return b->s; free: free(b->s); b->s = NULL; b->n = 0U; b->z = 0U; return NULL; } static __attribute__((nonnull(1, 2))) char* bbuf_cpy(bbuf_t *restrict b, const char *str, size_t ssz) { /* reduce to bbuf_cat() with zero offset */ b->n = 0U; return bbuf_cat(b, str, ssz); } static void yield_usg(const struct usg_s *arg); static void yield_opt(const struct opt_s *arg); static void yield_inter(const bbuf_t x[static 1U]); static void yield_setopt(yopt_t); #define DEBUG(args...) static int usagep(const char *line, size_t llen) { #define STREQLITP(x, lit) (!strncasecmp((x), lit, sizeof(lit) - 1)) static struct usg_s cur_usg; static bbuf_t umb[1U]; static bbuf_t cmd[1U]; static bbuf_t parg[1U]; static bbuf_t desc[1U]; static bool cur_usg_yldd_p; static bool umb_yldd_p; const char *sp; const char *up; const char *cp; const char *const ep = line + llen; if (UNLIKELY(line == NULL)) { goto yield; } DEBUG("USAGEP CALLED with %s", line); if (STREQLITP(line, "setopt")) { /* it's a setopt */ return 0; } else if (!STREQLITP(line, "usage:")) { if (only_whitespace_p(line, llen) && !desc->n) { return 1; } else if (!isspace(*line) && !cur_usg_yldd_p) { /* append to description */ cur_usg.desc = bbuf_cat(desc, line, llen); return 1; } yield: #define RESET cur_usg.cmd = cur_usg.parg = cur_usg.desc = NULL, desc->n = 0U if (!cur_usg_yldd_p) { yield_usg(&cur_usg); /* reset */ RESET; cur_usg_yldd_p = true; umb_yldd_p = true; } return 0; } else if (!cur_usg_yldd_p) { /* can't just goto yield because they wander off */ yield_usg(&cur_usg); /* reset */ RESET; cur_usg_yldd_p = true; umb_yldd_p = true; } /* overread whitespace then */ for (sp = line + sizeof("usage:") - 1; sp < ep && isspace(*sp); sp++); /* first thing should name the umbrella, find its end */ for (up = sp; sp < ep && !isspace(*sp); sp++); if (cur_usg.umb && !strncasecmp(cur_usg.umb, up, sp - up)) { /* nothing new and fresh */ ; } else { cur_usg.umb = bbuf_cpy(umb, up, sp - up); umb_yldd_p = false; } /* overread more whitespace and [--BLA] decls then */ overread: for (; sp < ep && isspace(*sp); sp++); /* we might be strafed with option decls here */ switch (*sp) { case '[': if (sp[1U] == '-') { /* might be option spec [-x], read on */ ; } else if (STREQLITP(sp + 1U, "OPTION")) { /* definitely an option marker innit? */ ; } else { /* could be posarg, better exit here */ break; } /* otherwise read till closing bracket */ for (sp++; sp < ep && *sp++ != ']';); /* and also read over `...' */ for (sp++; sp < ep && *sp == '.'; sp++); goto overread; default: /* best leave the loop */ break; } /* now it's time for the command innit */ for (cp = sp; sp < ep && !isspace(*sp); sp++); if (cur_usg.cmd && !strncasecmp(cur_usg.cmd, cp, sp - cp)) { /* nothing new and fresh */ ; } else if (!strncasecmp(cp, "command", sp - cp) || (cp[0] == '<' && sp[-1] == '>' && !strncasecmp(cp + 1U, "command", sp - cp - 2))) { /* special command COMMAND or */ cur_usg.cmd = NULL; } else if (*cp >= 'a' && *cp <= 'z' && umb_yldd_p) { /* we mandate commands start with a lower case alpha char */ cur_usg.cmd = bbuf_cpy(cmd, cp, sp - cp); } else { /* not a command, could be posarg innit, so rewind */ sp = cp; } /* now there might be positional args, snarf them */ for (; sp < ep && isspace(*sp); sp++); if (sp < ep) { cur_usg.parg = bbuf_cpy(parg, sp, ep - sp - 1U); } cur_usg_yldd_p = false; return 1; } static int optionp(const char *line, size_t llen) { static struct opt_s cur_opt; static bbuf_t desc[1U]; static bbuf_t lopt[1U]; static bbuf_t larg[1U]; const char *sp = line; const char *const ep = line + llen; if (UNLIKELY(line == NULL)) { goto yield; } DEBUG("OPTIONP CALLED with %s", line); /* overread whitespace */ for (; sp < ep && isspace(*sp); sp++) { if (*sp == '\t') { /* make a tab character count 8 in total */ sp += 7U; } } if ((sp - line >= 8 || (sp - line >= 1 && *sp != '-')) && (cur_opt.sopt || cur_opt.lopt)) { /* should be description */ goto desc; } yield: /* must yield the old current option before it's too late */ if (cur_opt.sopt || cur_opt.lopt) { yield_opt(&cur_opt); } /* complete reset */ memset(&cur_opt, 0, sizeof(cur_opt)); if (sp - line < 2) { /* can't be an option, can it? */ return 0; } else if (!*sp) { /* not an option either */ return 0; } /* no yield pressure anymore, try parsing the line */ sp++; if (*sp >= '0') { char sopt = *sp++; /* eat a comma as well */ if (*sp == ',') { sp++; } if (!isspace(*sp)) { /* don't know -x.SOMETHING? */ return 0; } /* start over with the new option */ sp++; cur_opt.sopt = sopt; if (*sp == '\0') { /* just the short option then innit? */ return 1; } else if (isspace(*sp)) { /* no arg name, no longopt */ ; } else if (*sp == '-') { /* must be a --long now, maybe */ sp++; } else { /* just an arg name */ const char *ap; if (*sp == '[') { cur_opt.oarg = 1U; sp++; } if (*sp == '=') { sp++; } for (ap = sp; sp < ep && isdashdash(*sp); sp++); cur_opt.larg = bbuf_cpy(larg, ap, sp - ap); if (cur_opt.oarg && *sp++ != ']') { /* maybe not an optarg? */ ; } if (*sp == '.') { /* could be mularg */ if (sp[1U] == '.' && sp[2U] == '.') { /* yay, 3 dots, read over dots */ for (sp += 3U; *sp == '.'; sp++); cur_opt.marg = 1U; } } } } else if (*sp == '-') { /* --option */ ; } else { /* don't know what this is */ return 0; } /* --option */ if (*sp++ == '-') { const char *op; for (op = sp; sp < ep && isdashdash(*sp); sp++); cur_opt.lopt = bbuf_cpy(lopt, op, sp - op); switch (*sp++) { case '[': if (*sp++ != '=') { /* just bullshit then innit? */ break; } /* otherwise optarg, fall through */ cur_opt.oarg = 1U; case '=':; /* has got an arg */ const char *ap; for (ap = sp; sp < ep && isdashdash(*sp); sp++); cur_opt.larg = bbuf_cpy(larg, ap, sp - ap); if (cur_opt.oarg && *sp++ != ']') { /* maybe not an optarg? */ ; } if (*sp == '.') { /* could be mularg */ if (sp[1U] == '.' && sp[2U] == '.') { /* yay, 3 dots, read over dots */ for (sp += 3U; *sp == '.'; sp++); cur_opt.marg = 1U; } } default: break; } } /* require at least one more space? */ ; /* space eater */ for (; sp < ep && isspace(*sp); sp++); /* don't free but reset the old guy */ desc->n = 0U; desc: with (size_t sz = llen - (sp - line)) { if (LIKELY(sz > 0U)) { cur_opt.desc = bbuf_cat(desc, sp, sz); } } return 1; } static int interp(const char *line, size_t llen) { static bbuf_t desc[1U]; bool only_ws_p = only_whitespace_p(line, llen); if (UNLIKELY(line == NULL)) { goto yield; } DEBUG("INTERP CALLED with %s", line); if (only_ws_p && desc->n) { yield: yield_inter(desc); /* reset */ desc->n = 0U; } else if (!only_ws_p) { if (STREQLITP(line, "setopt")) { /* not an inter */ return 0; } /* snarf the line */ bbuf_cat(desc, line, llen); return 1; } return 0; } static int setoptp(const char *line, size_t UNUSED(llen)) { if (UNLIKELY(line == NULL)) { return 0; } DEBUG("SETOPTP CALLED with %s", line); if (STREQLITP(line, "setopt")) { /* 'nother option */ const char *lp = line + sizeof("setopt"); if (0) { ; } else if (STREQLITP(lp, "allow-unknown-dash-options")) { yield_setopt(YOPT_ALLOW_UNKNOWN_DASH); } else if (STREQLITP(lp, "allow-unknown-dashdash-options")) { yield_setopt(YOPT_ALLOW_UNKNOWN_DASHDASH); } else { /* unknown setopt option */ } } return 0; } static const char nul_str[] = ""; static const char *const auto_types[] = {"auto", "flag"}; static FILE *outf; static struct { unsigned int no_auto_flags:1U; unsigned int no_auto_action:1U; } global_tweaks; static void __identify(char *restrict idn) { if (UNLIKELY(idn == NULL)) { return; } for (char *restrict ip = idn; *ip; ip++) { switch (*ip) { case '0' ... '9': case 'A' ... 'Z': case 'a' ... 'z': break; default: *ip = '_'; } } return; } static size_t count_pargs(const char *parg) { /* return max posargs as helper for auto-dashdash commands */ const char *pp; size_t res; for (res = 0U, pp = parg; *pp;) { /* allow [--] or -- as auto-dashdash declarators */ if (*pp == '[') { pp++; } if (*pp++ == '-') { if (*pp++ == '-') { if (*pp == ']' || isspace(*pp)) { /* found him! */ return res; } } /* otherwise not the declarator we were looking for * fast forward to the end */ for (; *pp && !isspace(*pp); pp++); } else { /* we know it's a bog-standard posarg for sure */ res++; /* check for ellipsis */ for (; *pp && *pp != '.' && !isspace(*pp); pp++); if (!*pp) { /* end of parg string anyway */ break; } if (*pp++ == '.' && *pp++ == '.' && *pp++ == '.') { /* ellipsis, set res to infinity and bog off */ break; } } /* fast forward over all the whitespace */ for (; *pp && isspace(*pp); pp++); } return 0U; } static char* make_opt_ident(const struct opt_s *arg) { static bbuf_t i[1U]; if (arg->lopt != NULL) { bbuf_cpy(i, arg->lopt, strlen(arg->lopt)); } else if (arg->sopt) { if (bbuf_cpy(i, "dash.", 5U) != NULL) { i->s[4U] = arg->sopt; } } else { static unsigned int cnt; if (bbuf_cpy(i, "idnXXXX", 7U) != NULL) { snprintf(i->s + 3U, 5U, "%u", cnt++); } } if (LIKELY(i->s != NULL)) { __identify(i->s); } return i->s; } static char* make_ident(const char *str) { static bbuf_t buf[1U]; if (LIKELY(bbuf_cpy(buf, str, strlen(str)) != NULL)) { __identify(buf->s); } return buf->s; } static void yield_help(void) { const char *type = auto_types[global_tweaks.no_auto_action]; fprintf(outf, "yuck_add_option([help], [h], [help], [%s])\n", type); fprintf(outf, "yuck_set_option_desc([help], [\ display this help and exit])\n"); return; } static void yield_version(void) { const char *type = auto_types[global_tweaks.no_auto_action]; fprintf(outf, "yuck_add_option([version], [V], [version], [%s])\n", type); fprintf(outf, "yuck_set_option_desc([version], [\ output version information and exit])\n"); return; } static void yield_usg(const struct usg_s *arg) { const char *parg = arg->parg ?: nul_str; size_t nparg = count_pargs(parg); if (arg->desc != NULL) { /* kick last newline */ massage_desc(arg->desc); } if (arg->cmd != NULL) { const char *idn = make_ident(arg->cmd); fprintf(outf, "\nyuck_add_command([%s], [%s], [%s])\n", idn, arg->cmd, parg); if (nparg) { fprintf(outf, "yuck_set_command_max_posargs([%s], [%zu])\n", idn, nparg); } if (arg->desc != NULL) { fprintf(outf, "yuck_set_command_desc([%s], [%s])\n", idn, arg->desc); } } else if (arg->umb != NULL) { const char *idn = make_ident(arg->umb); fprintf(outf, "\nyuck_set_umbrella([%s], [%s], [%s])\n", idn, arg->umb, parg); if (nparg) { fprintf(outf, "yuck_set_umbrella_max_posargs([%s], [%zu])\n", idn, nparg); } if (arg->desc != NULL) { fprintf(outf, "yuck_set_umbrella_desc([%s], [%s])\n", idn, arg->desc); } /* insert auto-help and auto-version */ if (!global_tweaks.no_auto_flags) { yield_help(); yield_version(); } } return; } static void yield_opt(const struct opt_s *arg) { char sopt[2U] = {arg->sopt, '\0'}; const char *opt = arg->lopt ?: nul_str; const char *idn = make_opt_ident(arg); if (arg->larg == NULL) { fprintf(outf, "yuck_add_option([%s], [%s], [%s], " "[flag]);\n", idn, sopt, opt); } else { const char *asufs[] = { nul_str, ", opt", ", mul", ", mul, opt" }; const char *asuf = asufs[arg->oarg | arg->marg << 1U]; fprintf(outf, "yuck_add_option([%s], [%s], [%s], " "[arg, %s%s]);\n", idn, sopt, opt, arg->larg, asuf); } if (arg->desc != NULL) { massage_desc(arg->desc); fprintf(outf, "yuck_set_option_desc([%s], [%s])\n", idn, arg->desc); } return; } static void yield_inter(const bbuf_t x[static 1U]) { if (x->n) { if (x->s[x->n - 1U] == '\n') { x->s[x->n - 1U] = '\0'; } massage_desc(x->s); fprintf(outf, "yuck_add_inter([%s])\n", x->s); } return; } static void yield_setopt(yopt_t yo) { switch (yo) { default: case YOPT_NONE: break; case YOPT_ALLOW_UNKNOWN_DASH: fputs("yuck_setopt_allow_unknown_dash\n", outf); break; case YOPT_ALLOW_UNKNOWN_DASHDASH: fputs("yuck_setopt_allow_unknown_dashdash\n", outf); break; } return; } static enum { UNKNOWN, SET_INTER, SET_UMBCMD, SET_OPTION, SET_SETOPT, } snarf_ln(char *line, size_t llen) { static unsigned int st; switch (st) { case UNKNOWN: case SET_UMBCMD: usage: /* first keep looking for Usage: lines */ if (usagep(line, llen)) { st = SET_UMBCMD; break; } else if (st == SET_UMBCMD) { /* reset state, go on with option parsing */ st = UNKNOWN; goto option; } case SET_OPTION: option: /* check them option things */ if (optionp(line, llen)) { st = SET_OPTION; break; } else if (st == SET_OPTION) { /* reset state, go on with usage parsing */ st = UNKNOWN; goto usage; } case SET_INTER: /* check for some intro texts */ if (interp(line, llen)) { st = SET_INTER; break; } else { /* reset state, go on with setopt parsing */ st = UNKNOWN; } case SET_SETOPT: /* check for setopt BLA lines */ if (setoptp(line, llen)) { st = SET_SETOPT; break; } else { /* reset state, go on with option parsing */ st = UNKNOWN; } default: break; } return UNKNOWN; } static int snarf_f(FILE *f) { char *line = NULL; size_t llen = 0U; #if defined HAVE_GETLINE for (ssize_t nrd; (nrd = getline(&line, &llen, f)) > 0;) { if (*line == '#') { continue; } snarf_ln(line, nrd); } #elif defined HAVE_FGETLN while ((line = fgetln(f, &llen)) != NULL) { if (*line == '#') { continue; } snarf_ln(line, llen); } #else # error neither getline() nor fgetln() available, cannot read file line by line #endif /* GETLINE/FGETLN */ /* drain */ snarf_ln(NULL, 0U); #if defined HAVE_GETLINE free(line); #endif /* HAVE_GETLINE */ return 0; } #if defined BOOTSTRAP static FILE* get_fn(int argc, char *argv[]) { FILE *res; if (argc > 1) { const char *fn = argv[1]; if (UNLIKELY((res = fopen(fn, "r")) == NULL)) { error("cannot open file `%s'", fn); } } else { res = stdin; } return res; } int main(int argc, char *argv[]) { int rc = 0; FILE *yf; if (UNLIKELY((yf = get_fn(argc, argv)) == NULL)) { rc = -1; } else { /* always use stdout */ outf = stdout; fputs("\ changequote([,])dnl\n\ divert([-1])\n", outf); /* let the snarfing begin */ rc = snarf_f(yf); fputs("\n\ changecom([//])\n\ divert[]dnl\n", outf); /* clean up */ fclose(yf); } return -rc; } #endif /* BOOTSTRAP */ #if !defined BOOTSTRAP #if !defined PATH_MAX # define PATH_MAX (256U) #endif /* !PATH_MAX */ static char dslfn[PATH_MAX]; static bool aux_in_path_p(const char *aux, const char *path, size_t pathz) { char fn[PATH_MAX]; char *restrict fp = fn; struct stat st[1U]; fp += xstrlncpy(fn, sizeof(fn), path, pathz); *fp++ = '/'; xstrlcpy(fp, aux, sizeof(fn) - (fp - fn)); if (stat(fn, st) < 0) { return false; } return S_ISREG(st->st_mode); } static ssize_t get_myself(char *restrict buf, size_t bsz) { ssize_t off; char *mp; #if defined __linux__ static const char myself[] = "/proc/self/exe"; if (UNLIKELY((off = readlink(myself, buf, bsz)) < 0)) { /* shame */ return -1; } #elif defined __NetBSD__ static const char myself[] = "/proc/curproc/exe"; if (UNLIKELY((off = readlink(myself, buf, bsz)) < 0)) { /* nawww */ return -1; } #elif defined __DragonFly__ static const char myself[] = "/proc/curproc/file"; if (UNLIKELY((off = readlink(myself, buf, bsz)) < 0)) { /* blimey */ return -1; } #elif defined __FreeBSD__ int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1}; /* make sure that \0 terminator fits */ buf[--bsz] = '\0'; if (UNLIKELY(sysctl(mib, countof(mib), buf, &bsz, NULL, 0) < 0)) { return -1; } /* we can be grateful they gave us the path, counting is our job */ off = strlen(buf); #elif defined __sun || defined sun snprintf(buf, bsz, "/proc/%d/path/a.out", getpid()); if (UNLIKELY((off = readlink(buf, buf, bsz)) < 0)) { return -1; } #elif defined __APPLE__ && defined __MACH__ uint32_t z = --bsz; if (_NSGetExecutablePath(buf, &z) != 0) { return -1; } /* good, do the counting */ off = strlen(buf); #else return -1; #endif /* go back to the dir bit */ for (mp = buf + off - 1U; mp > buf && *mp != '/'; mp--); /* should be bin/, go up one level */ *mp = '\0'; for (; mp > buf && *mp != '/'; mp--); /* check if we're right */ if (UNLIKELY(strcmp(++mp, "bin"))) { /* oh, it's somewhere but not bin/? */ return -1; } /* now just use share/yuck/ */ xstrlcpy(mp, "share/yuck/", bsz - (mp - buf)); mp += sizeof("share/yuck"); return mp - buf; } static int find_aux(char *restrict buf, size_t bsz, const char *aux) { /* look up path relative to binary position */ static char pkgdatadir[PATH_MAX]; static ssize_t pkgdatalen; static const char *tmplpath; static ssize_t tmplplen; const char *path; size_t plen; /* start off by snarfing the environment */ if (tmplplen == 0U) { if ((tmplpath = getenv("YUCK_TEMPLATE_PATH")) != NULL) { tmplplen = strlen(tmplpath); } else { /* just set it to something non-0 to indicate initting * and that also works with the loop below */ tmplplen = -1; tmplpath = (void*)0x1U; } } /* snarf pkgdatadir */ if (pkgdatalen == 0U) { pkgdatalen = get_myself(pkgdatadir, sizeof(pkgdatadir)); } /* go through the path first */ for (const char *pp = tmplpath, *ep, *const end = tmplpath + tmplplen; pp < end; pp = ep + 1U) { ep = strchr(pp, ':') ?: end; if (aux_in_path_p(aux, pp, ep - pp)) { path = pp; plen = ep - pp; goto bang; } } /* no luck with the env path then aye */ if (pkgdatalen > 0 && aux_in_path_p(aux, pkgdatadir, pkgdatalen)) { path = pkgdatadir; plen = pkgdatalen; goto bang; } #if defined YUCK_TEMPLATE_PATH path = YUCK_TEMPLATE_PATH; plen = strlenof(YUCK_TEMPLATE_PATH); if (aux_in_path_p(aux, path, plen)) { goto bang; } #endif /* YUCK_TEMPLATE_PATH */ /* not what we wanted at all, must be christmas */ return -1; bang: with (size_t z) { z = xstrlncpy(buf, bsz, path, plen); buf[z++] = '/'; xstrlcpy(buf + z, aux, bsz - z); } return 0; } static int find_dsl(void) { return find_aux(dslfn, sizeof(dslfn), "yuck.m4"); } static void unmassage_fd(int tgtfd, int srcfd) { static char buf[4096U]; for (ssize_t nrd; (nrd = read(srcfd, buf, sizeof(buf))) > 0;) { const char *bp = buf; const char *const ep = buf + nrd; unmassage_buf(buf, nrd); for (ssize_t nwr; bp < ep && (nwr = write(tgtfd, bp, ep - bp)) > 0; bp += nwr); } return; } static char *m4_cmdline[16U] = { YUCK_M4, }; static size_t cmdln_idx; static int prep_m4(void) { char *p; /* checkout the environment, look for M4 */ if ((p = getenv("M4")) == NULL) { cmdln_idx = 1U; return 0; } /* otherwise it's big string massaging business */ do { m4_cmdline[cmdln_idx++] = p; /* mimic a shell's IFS */ for (; *p && !isspace(*p); p++) { const char this = *p; switch (this) { default: break; case '"': case '\'': /* fast forward then */ while (*++p != this) { if (*p == '\\') { p++; } } break; } } if (!*p) { break; } /* otherwise it's an IFS */ for (*p++ = '\0'; isspace(*p); p++); } while (1); return 0; } static __attribute__((noinline)) int run_m4(const char *outfn, ...) { pid_t m4p; /* we need a bidirectional pipe (for the unmassaging) */ int intfd[2]; int outfd = STDOUT_FILENO; int rc; if (pipe(intfd) < 0) { error("pipe setup to/from m4 failed"); return -1; } else if (!cmdln_idx && prep_m4() < 0) { error("m4 preparations failed"); return -1; } /* command-line prepping */ with (va_list vap) { va_start(vap, outfn); for (size_t i = cmdln_idx; i < countof(m4_cmdline) && (m4_cmdline[i] = va_arg(vap, char*)) != NULL; i++); va_end(vap); } switch ((m4p = vfork())) { case -1: /* i am an error */ error("vfork for m4 failed"); return -1; default: break; case 0: /* redirect stdout -> intfd[1] */ dup2(intfd[1], STDOUT_FILENO); close(intfd[1]); close(intfd[0]); /* i am the child */ execvp(m4_cmdline[0U], m4_cmdline); error("execvp(m4) failed"); _exit(EXIT_FAILURE); } /* i am the parent */ close(intfd[1]); /* prep redirection */ if (outfn != NULL) { /* --output given */ const int outfl = O_RDWR | O_CREAT | O_TRUNC; if ((outfd = open(outfn, outfl, 0666)) < 0) { /* bollocks */ error("cannot open outfile `%s'", outfn); return -1; } } /* reroute m4's output */ unmassage_fd(outfd, intfd[0]); rc = 2; with (int st) { while (waitpid(m4p, &st, 0) != m4p); if (WIFEXITED(st)) { rc = WEXITSTATUS(st); } } if (outfn != NULL) { close(outfd); } return rc; } static int wr_pre(void) { fputs("\ changequote`'changequote([,])dnl\n\ divert([-1])\n", outf); return 0; } static int wr_suf(void) { fputs("\n\ changequote`'dnl\n\ divert`'dnl\n", outf); return 0; } static int wr_intermediary(char *const args[], size_t nargs) { int rc = 0; wr_pre(); if (nargs == 0U) { if (snarf_f(stdin) < 0) { errno = 0; error("cannot interpret directives on stdin"); rc = 1; } } for (unsigned int i = 0U; i < nargs && rc == 0; i++) { const char *fn = args[i]; FILE *yf; if (UNLIKELY((yf = fopen(fn, "r")) == NULL)) { error("cannot open file `%s'", fn); rc = 1; break; } else if (snarf_f(yf) < 0) { errno = 0; error("cannot interpret directives from `%s'", fn); rc = 1; } /* clean up */ fclose(yf); } /* reset to sane values */ wr_suf(); return rc; } static int wr_header(const char hdr[static 1U]) { /* massage the hdr bit a bit */ if (strcmp(hdr, "/dev/null")) { /* /dev/null just means ignore the header aye? */ const char *hp; if ((hp = strrchr(hdr, '/')) == NULL) { hp = hdr; } else { hp++; }; wr_pre(); fprintf(outf, "define([YUCK_HEADER], [%s])dnl\n", hp); wr_suf(); } return 0; } static int wr_man_date(void) { time_t now; const struct tm *tp; char buf[32U]; int rc = 0; if ((now = time(NULL)) == (time_t)-1) { rc = -1; } else if ((tp = gmtime(&now)) == NULL) { rc = -1; } else if (!strftime(buf, sizeof(buf), "%B %Y", tp)) { rc = -1; } else { fprintf(outf, "define([YUCK_MAN_DATE], [%s])dnl\n", buf); } return rc; } static int wr_man_pkg(const char *pkg) { fprintf(outf, "define([YUCK_PKG_STR], [%s])dnl\n", pkg); return 0; } static int wr_man_nfo(const char *nfo) { fprintf(outf, "define([YUCK_NFO_STR], [%s])dnl\n", nfo); return 0; } static int wr_man_incln(FILE *fp, char *restrict ln, size_t lz) { static int verbp; static int parap; if (UNLIKELY(ln == NULL)) { /* drain mode */ if (verbp) { fputs(".fi\n", fp); } } else if (lz <= 1U/*has at least a newline?*/) { if (verbp) { /* close verbatim mode */ fputs(".fi\n", fp); verbp = 0; } if (!parap) { fputs(".PP\n", fp); parap = 1; } } else if (*ln == '[' && ln[lz - 2U] == ']') { /* section */ char *restrict lp = ln + 1U; for (const char *const eol = ln + lz - 2U; lp < eol; lp++) { *lp = (char)toupper(*lp); } *lp = '\0'; fputs(".SH ", fp); fputs(ln + 1U, fp); fputs("\n", fp); /* reset state */ parap = 0; verbp = 0; } else if (ln[0U] == ' ' && ln[1U] == ' ' && !verbp) { fputs(".nf\n", fp); verbp = 1; goto cp; } else { cp: /* otherwise copy */ fwrite(ln, lz, sizeof(*ln), fp); parap = 0; } return 0; } static int wr_man_include(char **const inc) { char _ofn[] = P_tmpdir "/" "yuck_XXXXXX"; char *ofn = _ofn; FILE *ofp; char *line = NULL; size_t llen = 0U; FILE *fp; if (UNLIKELY((fp = fopen(*inc, "r")) == NULL)) { error("Cannot open include file `%s', ignoring", *inc); *inc = NULL; return -1; } else if (UNLIKELY((ofp = mkftempp(&ofn, sizeof(P_tmpdir))) == NULL)) { error("Cannot open output file `%s', ignoring", ofn); *inc = NULL; return -1; } /* make sure we pass on ofn */ *inc = strdup(ofn); #if defined HAVE_GETLINE for (ssize_t nrd; (nrd = getline(&line, &llen, fp)) > 0;) { wr_man_incln(ofp, line, nrd); } #elif defined HAVE_FGETLN while ((line = fgetln(fp, &llen)) != NULL) { wr_man_incln(ofp, line, llen); } #else # error neither getline() nor fgetln() available, cannot read file line by line #endif /* GETLINE/FGETLN */ /* drain */ wr_man_incln(ofp, NULL, 0U); #if defined HAVE_GETLINE free(line); #endif /* HAVE_GETLINE */ /* close files properly */ fclose(fp); fclose(ofp); return 0; } static int wr_man_includes(char *incs[], size_t nincs) { for (size_t i = 0U; i < nincs; i++) { /* massage file */ if (wr_man_include(incs + i) < 0) { continue; } else if (incs[i] == NULL) { /* something else is wrong */ continue; } /* otherwise make a note to include this file */ fprintf(outf, "\ append([YUCK_INCLUDES], [%s], [,])dnl\n", incs[i]); } return 0; } static int wr_version(const struct yuck_version_s *v, const char *vlit) { wr_pre(); if (v != NULL) { #if defined WITH_SCMVER const char *yscm = yscm_strs[v->scm]; fprintf(outf, "define([YUCK_SCMVER_VTAG], [%s])\n", v->vtag); fprintf(outf, "define([YUCK_SCMVER_SCM], [%s])\n", yscm); fprintf(outf, "define([YUCK_SCMVER_DIST], [%u])\n", v->dist); fprintf(outf, "define([YUCK_SCMVER_RVSN], [%0*x])\n", (int)(v->rvsn & 0x07U), v->rvsn >> 4U); if (!v->dirty) { fputs("define([YUCK_SCMVER_FLAG_CLEAN])\n", outf); } else { fputs("define([YUCK_SCMVER_FLAG_DIRTY])\n", outf); } /* for convenience */ fputs("define([YUCK_SCMVER_VERSION], [", outf); fputs(v->vtag, outf); if (v->scm > YUCK_SCM_TARBALL && v->dist) { fputc('.', outf); fputs(yscm_strs[v->scm], outf); fprintf(outf, "%u.%0*x", v->dist, (int)(v->rvsn & 0x07U), v->rvsn >> 4U); } if (v->dirty) { fputs(".dirty", outf); } fputs("])\n", outf); #else /* !WITH_SCMVER */ errno = 0, error("\ scmver support not built in but ptr %p given to wr_version()", v); #endif /* WITH_SCMVER */ } if (vlit != NULL) { fputs("define([YUCK_VERSION], [", outf); fputs(vlit, outf); fputs("])\n", outf); } wr_suf(); return 0; } static int rm_intermediary(const char *fn, int keepp) { if (!keepp) { if (unlink(fn) < 0) { error("cannot remove intermediary `%s'", fn); return -1; } } else { /* otherwise print a nice message so users know * the file we created */ errno = 0, error("intermediary `%s' kept", fn); } return 0; } static int rm_includes(char *const incs[], size_t nincs, int keepp) { int rc = 0; errno = 0; for (size_t i = 0U; i < nincs; i++) { char *restrict fn; if ((fn = incs[i]) != NULL) { if (!keepp && unlink(fn) < 0) { error("cannot remove intermediary `%s'", fn); rc = -1; } else if (keepp) { /* otherwise print a nice message so users know * the file we created */ errno = 0, error("intermediary `%s' kept", fn); } free(fn); } } return rc; } #endif /* !BOOTSTRAP */ #if !defined BOOTSTRAP #include "yuck.yucc" static int cmd_gen(const struct yuck_cmd_gen_s argi[static 1U]) { static char _deffn[] = P_tmpdir "/" "yuck_XXXXXX"; static char gencfn[PATH_MAX]; static char genhfn[PATH_MAX]; char *deffn = _deffn; int rc = 0; if (argi->no_auto_flags_flag) { global_tweaks.no_auto_flags = 1U; } if (argi->no_auto_actions_flag) { global_tweaks.no_auto_action = 1U; } /* deal with the output first */ if (UNLIKELY((outf = mkftempp(&deffn, sizeof(P_tmpdir))) == NULL)) { error("cannot open intermediate file `%s'", deffn); return -1; } /* write up our findings in DSL language */ rc = wr_intermediary(argi->args, argi->nargs); /* deal with hard wired version numbers */ if (argi->version_arg) { rc += wr_version(NULL, argi->version_arg); } /* special directive for the header or is it */ if (argi->header_arg != NULL) { rc += wr_header(argi->header_arg); } /* and we're finished with the intermediary */ fclose(outf); /* only proceed if there has been no error yet */ if (rc) { goto out; } else if (find_dsl() < 0) { /* error whilst finding our DSL and things */ error("cannot find yuck dsl file"); rc = 2; goto out; } else if (find_aux(gencfn, sizeof(gencfn), "yuck-coru.c.m4") < 0 || find_aux(genhfn, sizeof(genhfn), "yuck-coru.h.m4") < 0) { error("cannot find yuck template files"); rc = 2; goto out; } /* now route that stuff through m4 */ with (const char *outfn = argi->output_arg, *cusfn = argi->custom_arg ?: "/dev/null", *hdrfn) { if ((hdrfn = argi->header_arg) != NULL) { /* run a special one for the header */ if ((rc = run_m4(hdrfn, dslfn, deffn, genhfn, NULL))) { break; } /* now run the whole shebang for the beef code */ rc = run_m4(outfn, dslfn, deffn, cusfn, gencfn, NULL); break; } /* standard case: pipe directives, then header, then code */ rc = run_m4(outfn, dslfn, deffn, cusfn, genhfn, gencfn, NULL); } out: /* unlink include files */ rm_intermediary(deffn, argi->keep_flag); return rc; } static int cmd_genman(const struct yuck_cmd_genman_s argi[static 1U]) { static char _deffn[] = P_tmpdir "/" "yuck_XXXXXX"; static char genmfn[PATH_MAX]; char *deffn = _deffn; int rc = 0; /* deal with the output first */ if (UNLIKELY((outf = mkftempp(&deffn, sizeof(P_tmpdir))) == NULL)) { error("cannot open intermediate file `%s'", deffn); return -1; } /* write up our findings in DSL language */ rc = wr_intermediary(argi->args, argi->nargs); if (argi->version_string_arg) { rc += wr_version(NULL, argi->version_string_arg); } else if (argi->version_file_arg) { #if defined WITH_SCMVER struct yuck_version_s v[1U]; const char *verfn = argi->version_file_arg; if (yuck_version_read(v, verfn) < 0) { error("cannot read version number from `%s'", verfn); rc--; } else { rc += wr_version(v, NULL); } #else /* !WITH_SCMVER */ errno = 0; error("\ scmver support not built in, --version-file cannot be used"); #endif /* WITH_SCMVER */ } /* reset to sane values */ wr_pre(); /* at least give the man page template an idea for YUCK_MAN_DATE */ rc += wr_man_date(); if (argi->package_arg) { /* package != umbrella */ rc += wr_man_pkg(argi->package_arg); } if (argi->info_page_arg) { const char *nfo; if ((nfo = argi->info_page_arg) == YUCK_OPTARG_NONE) { nfo = "YUCK_PKG_STR"; } rc += wr_man_nfo(nfo); } /* go through includes */ wr_man_includes(argi->include_args, argi->include_nargs); /* reset to sane values */ wr_suf(); /* and we're finished with the intermediary */ fclose(outf); /* only proceed if there has been no error yet */ if (rc) { goto out; } else if (find_dsl() < 0) { /* error whilst finding our DSL and things */ error("cannot find yuck dsl and template files"); rc = 2; goto out; } else if (find_aux(genmfn, sizeof(genmfn), "yuck.man.m4") < 0) { error("cannot find yuck template for man pages"); rc = 2; goto out; } /* now route that stuff through m4 */ with (const char *outfn = argi->output_arg) { /* standard case: pipe directives, then header, then code */ rc = run_m4(outfn, dslfn, deffn, genmfn, NULL); } out: rm_includes(argi->include_args, argi->include_nargs, argi->keep_flag); rm_intermediary(deffn, argi->keep_flag); return rc; } static int cmd_gendsl(const struct yuck_cmd_gendsl_s argi[static 1U]) { int rc = 0; if (argi->no_auto_flags_flag) { global_tweaks.no_auto_flags = 1U; } if (argi->no_auto_actions_flag) { global_tweaks.no_auto_action = 1U; } /* bang to stdout or argi->output_arg */ with (const char *outfn = argi->output_arg) { if (outfn == NULL) { outf = stdout; } else if ((outf = fopen(outfn, "w")) == NULL) { error("cannot open outfile `%s'", outfn); return 1; } } rc += wr_intermediary(argi->args, argi->nargs); if (argi->version_arg) { rc += wr_version(NULL, argi->version_arg); } return rc; } static int cmd_scmver(const struct yuck_cmd_scmver_s argi[static 1U]) { #if defined WITH_SCMVER struct yuck_version_s v[1U]; struct yuck_version_s ref[1U]; const char *const reffn = argi->reference_arg; const char *const infn = argi->args[0U]; int rc = 0; /* read the reference file before it goes out of fashion */ if (reffn && yuck_version_read(ref, reffn) < 0 && /* only be fatal if we actually want to use the reference file */ argi->use_reference_flag) { error("cannot read reference file `%s'", reffn); return 1; } else if (reffn == NULL && argi->use_reference_flag) { errno = 0, error("\ flag -n|--use-reference requires -r|--reference parameter"); return 1; } else if (!argi->use_reference_flag && yuck_version(v, infn) < 0) { if (argi->ignore_noscm_flag) { /* allow graceful exit through --ignore-noscm */ return 0; } errno = 0, error("cannot determine SCM"); return 1; } if (reffn && argi->use_reference_flag) { /* must populate v then */ *v = *ref; } else if (reffn && yuck_version_cmp(v, ref)) { /* version stamps differ */ if (argi->verbose_flag) { errno = 0, error("scm version differs from reference"); } /* try to update the reference file then */ if (yuck_version_write(argi->reference_arg, v) < 0) { if (argi->verbose_flag) { error("cannot write reference file"); } /* degrade to using the reference file */ *v = *ref; rc = 0; } else { /* reserve exit code 3 for `updated reference file' */ rc = 3; } } else if (reffn && !argi->force_flag) { /* make sure the output file exists */ const char *const outfn = argi->output_arg; if (outfn == NULL || regfilep(outfn)) { /* don't worry about anything then */ return 0; } /* otherwise create at least one version of the output */ } if (infn != NULL && regfilep(infn)) { static char _scmvfn[] = P_tmpdir "/" "yscm_XXXXXX"; static char tmplfn[PATH_MAX]; char *scmvfn = _scmvfn; /* try the local dir first */ if ((outf = mkftempp(&scmvfn, sizeof(P_tmpdir))) == NULL) { error("cannot open intermediate file `%s'", scmvfn); rc = 1; } else if (find_aux(tmplfn, sizeof(tmplfn), "yuck-scmver.m4") < 0) { error("cannot find yuck template for version strings"); rc = 1; } else { const char *outfn = argi->output_arg; /* write the actual version info */ rc += wr_version(v, NULL); /* and we're finished with the intermediary */ fclose(outf); /* macro massage, vtmpfn is the template file */ rc += run_m4(outfn, scmvfn, tmplfn, infn, NULL); rm_intermediary(scmvfn, argi->keep_flag); } } else { fputs(v->vtag, stdout); if (v->scm > YUCK_SCM_TARBALL && v->dist) { fputc('.', stdout); fputs(yscm_strs[v->scm], stdout); fprintf(stdout, "%u.%0*x", v->dist, (int)(v->rvsn & 0x07U), v->rvsn >> 4U); } if (v->dirty) { fputs(".dirty", stdout); } fputc('\n', stdout); } return rc; #else /* !WITH_SCMVER */ fputs("scmver support not built in\n", stderr); return argi->cmd == YUCK_CMD_SCMVER; #endif /* WITH_SCMVER */ } static int cmd_config(const struct yuck_cmd_config_s argi[static 1U]) { const char *const fn = argi->output_arg; FILE *of = stdout; if (fn != NULL && (of = fopen(fn, "w")) == NULL) { error("cannot open file `%s'", fn); return -1; } if (argi->m4_flag) { fputs(YUCK_M4, of); fputc('\n', of); } return fclose(of); } int main(int argc, char *argv[]) { yuck_t argi[1U]; int rc = 0; if (yuck_parse(argi, argc, argv) < 0) { rc = 1; goto out; } switch (argi->cmd) { default: fputs("\ No valid command specified.\n\ See --help to obtain a list of available commands.\n", stderr); rc = 1; goto out; case YUCK_CMD_GEN: if ((rc = cmd_gen((const void*)argi)) < 0) { rc = 1; } break; case YUCK_CMD_GENDSL: if ((rc = cmd_gendsl((const void*)argi)) < 0) { rc = 1; } break; case YUCK_CMD_GENMAN: if ((rc = cmd_genman((const void*)argi)) < 0) { rc = 1; } break; case YUCK_CMD_SCMVER: if ((rc = cmd_scmver((const void*)argi)) < 0) { rc = 1; } break; case YUCK_CMD_CONFIG: if ((rc = cmd_config((const void*)argi)) < 0) { rc = 1; } break; } out: yuck_free(argi); return rc; } #endif /* !BOOTSTRAP */ /* yuck.c ends here */ dateutils-0.4.5/build-aux/yuck.m4000066400000000000000000000275621335042257000166420ustar00rootroot00000000000000changequote`'changequote([,])dnl divert([-1]) ## this is a little domain language for the yuck processor # foreachq(x, [item_1, item_2, ..., item_n], stmt) # quoted list, alternate improved version define([foreachq], [ifelse([$2], [], [], [pushdef([$1])_$0([$1], [$3], [], $2)popdef([$1])])]) define([_foreachq], [ifelse([$#], [3], [], [define([$1], [$4])$2[]$0([$1], [$2], shift(shift(shift($@))))])]) #### append $2 to $1, separated by $3. define([append], [define([$1], ifdef([$1], [defn([$1])[$3]])[$2])]) ## like append, but append only non-empty arguments define([append_ne], [ifelse([$2], [], [], [append([$1], [$2], [$3])])]) ## like append_ne, but append only non-existing arguments define([append_nene], [ifelse(index([$3]defn([$1])[$3], [$3$2$3]), [-1], [append_ne([$1], [$2], [$3])])]) define([appendq], [define([$1], ifdef([$1], [defn([$1])[$3]])dquote([$2]))]) ## like appendq, but append only non-empty arguments define([appendq_ne], [ifelse([$2], [], [], [append([$1], dquote([$2]), [$3])])]) ## like appendq_ne, but append only non-existing arguments define([appendq_nene], [ifelse(index([$3]defn([$1])[$3], [$3]dquote($2)[$3]), [-1], [appendq_ne([$1], [$2], [$3])])]) define([first_nonnil], [ifelse([$#], [0], [], [$1], [], [first_nonnil(shift($@))], [], [], [$1])]) define([first], [_first($*)]) define([_first], [$1]) define([second], [_second($*)]) define([_second], [$2]) define([thirds], [_thirds($*)]) define([_thirds], [quote(shift(shift($@)))]) define([quote], [ifelse([$#], [0], [], [[$*]])]) define([dquote], [[$@]]) define([equote], [dquote($*)]) define([backquote], [_$0([$1], [(], -=<{($1)}>=-, [}>=-])]) define([_backquote], [dnl ifelse([$4], [}>=-], [dnl changequote([-=<{$2], [)}>=-])$3changequote([, ])], [dnl else $0([$1], [($2], -=<{($2$1)}>=-, [}>=-])_ignore$2])]) define([_ignore]) define([_splice], [ifelse(eval([$#] > [3]), [0], [[$1], [$2], [$3]], [[$1], [$2], [$3], _splice([$1], shift(shift(shift($@))))])]) define([cond], [ifelse([$#], [0], [], [$#], [1], [$1], [_$0($@)])]) define([_cond], [dnl ifelse([$1], [$2], [$3], [$#], [3], [], [$#], [4], [$4], [$0([$1], shift(shift(shift($@))))])]) define([downcase], [dnl translit([$1], [ABCDEFGHIJKLMNOPQRSTUVWXYZ], [abcdefghijklmnopqrstuvwxyz])[]dnl ]) define([upcase], [dnl translit([$1], [abcdefghijklmnopqrstuvwxyz], [ABCDEFGHIJKLMNOPQRSTUVWXYZ])[]dnl ]) ## select a diversion, clearing all other diversions define([select_divert], [divert[]undivert($1)[]divert(-1)[]undivert[]divert(0)]) define([yuck_set_version], [dnl define([YUCK_VERSION], [$1]) ]) ## yuck_set_umbrella([ident], [umbrella], [[posarg]]) define([yuck_set_umbrella], [dnl define([YUCK_UMB], [$1]) define([YUCK_UMB_STR], [$2]) define([YUCK_UMB_POSARG], [$3]) ]) ## yuck_set_umbrella_desc([ident], [desc]) define([yuck_set_umbrella_desc], [dnl define([YUCK_UMB_$1_desc], [$2]) ## define yuck_add_inter here, corresponding to IDENT define([YUCK_INTER_CMD], [YUCK_UMB_$1_desc]) ]) ## yuck_set_umbrella_max_posargs([ident], [N]) define([yuck_set_umbrella_max_posargs], [dnl define([YUCK_UMB_$1_max_posargs], [$2]) define([YUCK_MAX_POSARGS], [$2]) ]) ## yuck_add_command([ident], [command], [[posarg]]) define([yuck_add_command], [dnl define([YUCK_CMD], [$1]) append_nene([YUCK_ALL_CMDS], [$1], [,]) define([YUCK_$1_STR], [$2]) define([YUCK_POSARG_$1], [$3]) ]) ## yuck_set_command_desc([ident], [desc]) define([yuck_set_command_desc], [dnl define([YUCK_CMD_$1_desc], [$2]) ## define yuck_add_inter here, corresponding to IDENT define([YUCK_INTER_CMD], [YUCK_CMD_$1_desc]) ]) ## yuck_set_umbrella_max_posargs([ident], [N]) define([yuck_set_command_max_posargs], [dnl define([YUCK_CMD_$1_max_posargs], [$2]) ]) ## yuck_add_inter([desc]) #### append interim DESC to last command desc define([yuck_add_inter], [dnl append(defn([YUCK_INTER_CMD]), [$1], [ ]) ]) ## yuck_add_option([ident], [short], [long], [type]) define([yuck_add_option], [dnl ## quote the elements of the type arg first ## before any possible expansion is in scope pushdef([type], equote([$4])) pushdef([ident], [$1]) pushdef([cmd], defn([YUCK_CMD])) ifelse([$2], [], [], index([0123456789], [$2]), [-1], [], [dnl else define([YUCK_SHORTS_HAVE_NUMERALS], [1]) ]) ifdef([YUCK_]defn([cmd])[_]defn([ident])[_canon], [], [dnl ## process only if new appendq_ne([YUCK_]defn([cmd])[_I], defn([ident]), [,]) ## forward maps define([YUCK_]defn([cmd])[_]defn([ident])[_canon], defn([ident])) define([YUCK_]defn([cmd])[_]defn([ident])[_type], defn([type])) ## reverse maps define([YUCK_]defn([cmd])[_]defn([ident])[_short], [$2]) define([YUCK_]defn([cmd])[_]defn([ident])[_long], [$3]) ]) popdef([ident]) popdef([cmd]) popdef([type]) ]) ## yuck_set_option_desc([ident], [desc]) define([yuck_set_option_desc], [dnl define([YUCK_]defn([YUCK_CMD])[_$1_desc], [$2]) ]) ## some yopts here, mostly flags define([yuck_setopt_allow_unknown_dash], [dnl define([YOPT_ALLOW_UNKNOWN_DASH]) ]) define([yuck_setopt_allow_unknown_dashdash], [dnl define([YOPT_ALLOW_UNKNOWN_DASHDASH]) ]) ## helpers for the m4c and m4h ## yuck_canon([opt], [[cmd]]) define([yuck_canon], [defn([YUCK_$2_$1_canon])]) ## yuck_option_type([opt], [[cmd]]) define([yuck_option_type], [defn([YUCK_$2_$1_type])]) ## yuck_type([type-spec]) define([yuck_type], [first([$1])]) ## yuck_type_name([type-spec]) define([yuck_type_name], [second([$1])]) ## yuck_type_sufx([type-spec]) define([yuck_type_sufx], [thirds([$1])]) ## yuck_slot_identifier([option], [[cmd]]) define([yuck_slot_identifier], [dnl pushdef([canon], yuck_canon([$1], [$2]))dnl pushdef([type], yuck_option_type([$1], [$2]))dnl dnl defn([canon])[_]yuck_type(defn([type]))[]dnl cond(yuck_type_sufx(defn([type])), [mul], [s], [mul,opt], [s])[]dnl dnl popdef([canon])dnl popdef([type])dnl ]) ## yuck_cnt_slot([option], [[cmd]]) define([yuck_cnt_slot], [dnl pushdef([type], yuck_option_type([$1], [$2]))dnl ifelse(yuck_type(defn([type])), [arg], [dnl ifelse(first(yuck_type_sufx(defn([type]))), [mul], [dnl pushdef([idn], [yuck_canon([$1], [$2])[_nargs]])dnl ifelse([$2], [], [idn], [$2.idn])[]dnl popdef([idn])dnl ])[]dnl ])[]dnl popdef([type])dnl ]) ## yuck_slot([option], [[cmd]]) define([yuck_slot], [dnl pushdef([idn], yuck_slot_identifier([$1], [$2]))dnl dnl ifelse([$2], [], defn([idn]), [$2.]defn([idn]))[]dnl dnl popdef([idn])dnl ]) ## yuck_iftype([opt], [cmd], [type], [body], [[type], [body]]...) define([yuck_iftype], [dnl pushdef([type], yuck_option_type([$1], [$2]))dnl pushdef([tsuf], yuck_type_sufx(defn([type])))dnl pushdef([res], yuck_type(defn([type])))dnl append_ne([res], defn([tsuf]), [,])[]dnl []ifelse(_splice(defn([res]), shift(shift($@))))[]dnl popdef([tsuf])dnl popdef([type])dnl popdef([res])dnl ]) ## yuck_umbcmds(), umbrella + commands define([yuck_umbcmds], [ifdef([YUCK_ALL_CMDS], [[,]defn([YUCK_ALL_CMDS])], dquote([[]]))]) ## yuck_cmds(), just the commands define([yuck_cmds], [defn([YUCK_ALL_CMDS])]) ## yuck_cmd([command]) define([yuck_cmd], [upcase(defn([YUCK_UMB]))[_CMD_]ifelse([$1], [], [NONE], [upcase([$1])])]) ## yuck_cmd_string define([yuck_cmd_string], [defn([YUCK_]$1[_STR])]) ## yuck_cmd_posarg define([yuck_cmd_posarg], [defn([YUCK_POSARG_]$1)]) ## yuck_umb_desc([[umb]]) getter for the umbrella description define([yuck_umb_desc], [defn([YUCK_UMB_]ifelse([$1], [], defn([YUCK_UMB]), [$1])[_desc])]) ## yuck_cmd_desc([cmd]) getter for the command description define([yuck_cmd_desc], [defn([YUCK_CMD_$1_desc])]) ## yuck_idents([cmd]) define([yuck_idents], [defn([YUCK_$1_I])]) ## yuck_short([ident], [[cmd]]) define([yuck_short], [defn([YUCK_$2_$1_short])]) ## yuck_long([ident], [[cmd]]) define([yuck_long], [defn([YUCK_$2_$1_long])]) ## yuck_option_desc([ident], [[cmd]]) define([yuck_option_desc], [defn([YUCK_$2_$1_desc])]) ## type actions define([_yuck_option_action], [dnl pushdef([type], yuck_option_type([$1], [$2]))dnl pushdef([prim], yuck_type(defn([type])))dnl pushdef([sufx], yuck_type_sufx(defn([type])))dnl quote([yuck_]defn([prim])ifelse(defn([sufx]), [], [], [_]translit(defn([sufx]), [,], [_]))[_action][(quote([$1]), quote([$2]))])dnl popdef([type])dnl popdef([prim])dnl popdef([sufx])dnl ])dnl define([yuck_expand], [$1]) define([yuck_option_action], [yuck_expand(_$0([$1], [$2]))]) ## yuck_option_help_lhs([ident], [[cmd]]) define([yuck_option_help_lhs], [dnl pushdef([s], [backquote([yuck_short([$1], [$2])])])dnl pushdef([l], [backquote([yuck_long([$1], [$2])])])dnl pushdef([type], yuck_option_type([$1], [$2]))dnl pushdef([prel], ifelse(l, [], [], [=]))dnl pushdef([yuck_arg_action], [defn([prel])[]yuck_type_name(yuck_option_type([$1], [$2]))])dnl pushdef([yuck_arg_opt_action], [defn([prel])[]yuck_type_name(yuck_option_type([$1], [$2]))])dnl pushdef([yuck_arg_mul_action], [defn([prel])[]yuck_type_name(yuck_option_type([$1], [$2]))...])dnl pushdef([yuck_arg_mul_opt_action], [defn([prel])[]yuck_type_name(yuck_option_type([$1], [$2]))...])dnl [ ]ifelse(s, [], [ ], [-s[]ifelse(l, [], [], [[, ]])])[]dnl ifelse(l, [], [], [--l])[]dnl ifelse(yuck_type(defn([type])), [arg], [dnl ifelse(l, [], [ ], [])backquote([yuck_option_action([$1], [$2])])[]dnl ])[]dnl popdef([type])dnl popdef([prel])dnl popdef([s])dnl popdef([l])dnl popdef([yuck_arg_action])dnl popdef([yuck_arg_opt_action])dnl popdef([yuck_arg_mul_action])dnl popdef([yuck_arg_mul_opt_action])dnl ]) define([xleft], [_$0([$1], 0, [$2])]) define([_xleft], [dnl ifelse(eval(incr(incr([$2])) <= [$3]), [1], [dnl substr([$1], [$2], 2)[]$0([$1], incr(incr([$2])), [$3])[]dnl ], eval(incr([$2]) <= [$3]), [1], [dnl substr([$1], [$2], 1)[]dnl ])[]dnl ]) define([xright], [_$0([$1], [$2])]) define([_xright], [dnl ifelse(eval([$2] >= len([$1])), [0], [dnl substr([$1], [$2], 2)[]$0([$1], incr(incr([$2])))[]dnl ])[]dnl ]) define([yuck_esc], [backquote([_$0([$1], [$2], [$3], [$4])])]) define([_yuck_esc], [dnl pushdef([__next_sep], index([$1], [$2]))[]dnl ifelse([$1], [], [], defn([__next_sep]), [-1], [$4[$1]], [dnl [$4]xleft([$1], defn([__next_sep]))[$3]dnl $0(backquote([xright([$1], eval(defn([__next_sep]) + len([$2])))]), [$2], [$3], [$4])[]dnl ])[]dnl popdef([__next_sep])dnl ])dnl define([yuck_indent_line], [yuck_esc([$1], [ ], [ ], [ ])]) ## yuck_option_help_line([ident], [[cmd]]) define([yuck_option_help_line], [dnl pushdef([lhs], [backquote([yuck_option_help_lhs([$1], [$2])])])dnl pushdef([desc], [yuck_option_desc([$1], [$2])])dnl pushdef([indesc], [yuck_indent_line(backquote([desc]))])dnl pushdef([lenlhs], len(lhs))dnl ifelse(indesc, [], [lhs], eval(lenlhs >= 23), [0], [dnl lhs[]backquote([xright(indesc, lenlhs)])[]dnl ], eval(lenlhs >= 24), [0], [dnl lhs[]backquote([xright(indesc, decr(lenlhs))])[]dnl ], [dnl lhs[ ]backquote([indesc])[]dnl ]) popdef([lenlhs])dnl popdef([indesc])dnl popdef([desc])dnl popdef([lhs])dnl ]) ## yuck_first_line([string]) define([yuck_first_line], [dnl pushdef([lnlen], [index([$1], [ ])])dnl backquote([ifelse(lnlen, -1, [$1], [xleft([$1], lnlen)])])[]dnl popdef([lnlen])dnl ]) ## yuck_cmd_line([cmd]) define([yuck_cmd_line], [dnl pushdef([lhs], [backquote([yuck_cmd_string([$1])])])dnl pushdef([indesc], [dnl yuck_first_line(backquote([yuck_cmd_desc([$1])]))])dnl pushdef([lenlhs], len(lhs))dnl ifelse(indesc, [], [lhs], eval(lenlhs >= 11), [0], [dnl lhs[]backquote([xright(indesc, lenlhs)])[]dnl ], eval(lenlhs >= 12), [0], [dnl lhs[]backquote([xright(indesc, decr(lenlhs))])[]dnl ], [dnl lhs backquote([indesc])[]dnl ])dnl popdef([lenlhs])dnl popdef([indesc])dnl popdef([lhs])dnl ]) ## \n -> \\n\\ define([yuck_esc_newline], [yuck_esc([$1], [ ], [\n\ ])]) ## " -> \" define([yuck_esc_quote], [yuck_esc([$1], ["], [\"])])dnl " ## \ -> \\ define([yuck_esc_backslash], [yuck_esc([$1], [\], [\\])])dnl define([yuck_C_literal], [dnl yuck_esc_newline(yuck_esc_quote(yuck_esc_backslash([$1])))[]dnl ])dnl ## coroutine stuff define([yield], [goto $1; back_from_$1:]) define([coroutine], [define([this_coru], [$1])$1:]) define([resume], [goto back_from_[]this_coru]) define([resume_at], [goto $1]) define([quit], [goto out]) divert[]dnl changequote`'dnl dateutils-0.4.5/build-aux/yuck.man.m4000066400000000000000000000054121335042257000174020ustar00rootroot00000000000000.\" auto generated by yuck -*- nroff -*- changequote`'changequote([,])dnl ifdef([YUCK_VERSION], [], [dnl else (!YUCK_VERSION) ifdef([YUCK_SCMVER_VERSION], [dnl then define([YUCK_VERSION], [YUCK_SCMVER_VERSION])[]dnl ], [dnl else (!YUCK_SCMVER_VERSION) define([YUCK_VERSION], [unknown])dnl ])dnl ])dnl define([ucase], [translit([$1], [abcdefghijklmnopqrstuvwxyz], [ABCDEFGHIJKLMNOPQRSTUVWXYZ])])dnl ifdef([YUCK_PKG_STR], [], [define([YUCK_PKG_STR], [YUCK_UMB_STR])])dnl .TH ucase(YUCK_UMB_STR) "1" "YUCK_MAN_DATE" "YUCK_PKG_STR YUCK_VERSION" "User Commands" .SH NAME pushdef([umb_desc], [yuck_first_line(yuck_umb_desc())])dnl pushdef([alt_desc], [manual page for YUCK_PKG_STR YUCK_VERSION])dnl YUCK_UMB_STR - first_nonnil(umb_desc, alt_desc) popdef([umb_desc])dnl popdef([alt_desc])dnl .SH SYNOPSIS .B YUCK_UMB_STR [[\fIOPTION\fR]]...[ ]dnl ifelse(yuck_cmds(), [], [], [\fICOMMAND\fR]) []dnl yuck_esc(dnl yuck_esc(dnl yuck_esc(dnl yuck_esc(dnl yuck_esc(translit(defn([YUCK_UMB_POSARG]), [[]], []), [ -], [\fR -]), [ ], [ \fI]), [], [\fR\fI]), [], [\fR]), [...], [\fR...]) .SH DESCRIPTION yuck_umb_desc() ifelse(yuck_cmds(), [], [], [dnl .PP \fICOMMAND\fR may be one of: foreachq([__CMD__], yuck_cmds(), [dnl .TP .B yuck_cmd_string(__CMD__) . yuck_cmd_desc(__CMD__) ])dnl ])dnl .PP define([yuck_man_option], [dnl pushdef([lhs], [yuck_option_help_lhs([$1], [$2])])dnl yuck_esc(dnl yuck_esc(dnl yuck_esc(dnl yuck_esc(dnl yuck_esc(dnl yuck_esc(dnl yuck_esc(lhs, [,], [\fR,]), [ -], [ \fB-]), [], [\fR]), [=], [\fR=]), [=], [=\fI]), [], [\fR]), [...], [\fR...])dnl popdef([lhs])dnl ]) Recognized \fIOPTION\fRs: foreachq([__IDN__], yuck_idents(), [dnl .TP .B yuck_man_option(defn([__IDN__]), []) yuck_option_desc(defn([__IDN__]), []) ])dnl dnl ifelse(yuck_cmds(), [], [], [dnl .SH COMMANDS ])dnl foreachq([__CMD__], yuck_cmds(), [ .P .B YUCK_UMB_STR yuck_cmd_string(__CMD__) [[\fIOPTION\fR]]... yuck_esc(dnl yuck_esc(dnl yuck_esc(dnl yuck_esc(dnl yuck_esc(translit(yuck_cmd_posarg(__CMD__), [[]], []), [ -], [\fR -]), [ ], [ \fI]), [], [\fR\fI]), [], [\fR]), [...], [\fR...]) .br yuck_cmd_desc(C) .P \fIOPTION\fRs specific to the \fB[]yuck_cmd_string(__CMD__)\fR command: foreachq([__IDN__], yuck_idents(__CMD__), [dnl .TP .B yuck_option_help_lhs(defn([__IDN__]), defn([__CMD__])) yuck_option_desc(defn([__IDN__]), defn([__CMD__])) ])dnl ])dnl foreachq([__INC__], defn([YUCK_INCLUDES]), [dnl include(__INC__) ]) ifdef([YUCK_NFO_STR], [ .SH "SEE ALSO" The full documentation for .B YUCK_UMB_STR is maintained as a Texinfo manual. If the .B info and .B YUCK_UMB_STR programs are properly installed at your site, the command .IP .B info ifelse(YUCK_NFO_STR, YUCK_UMB_STR, [YUCK_NFO_STR], [(YUCK_NFO_STR)YUCK_UMB_STR]) .PP should give you access to the complete manual. ])dnl .\" yuck.m4man ends here changequote`'dnl dateutils-0.4.5/build-aux/yuck.mk000066400000000000000000000007141335042257000167170ustar00rootroot00000000000000## bootstrapping rules, made for inclusion in your own Makefiles yuck.m4i: yuck.yuck $(MAKE) $(AM_MAKEFLAGS) yuck-bootstrap $(AM_V_GEN) $(builddir)/yuck-bootstrap$(EXEEXT) $(srcdir)/yuck.yuck > $@ \ || { rm -f -- $@; false; } yuck.yucc: yuck.m4i yuck.m4 yuck-coru.h.m4 yuck-coru.c.m4 $(AM_V_GEN) $(M4) $(srcdir)/yuck.m4 yuck.m4i \ $(srcdir)/yuck-coru.h.m4 $(srcdir)/yuck-coru.c.m4 | \ tr '\002\003\016\017' '[]()' > $@ \ || { rm -f -- $@; false; } dateutils-0.4.5/build-aux/yuck.yuck000066400000000000000000000053201335042257000172610ustar00rootroot00000000000000Usage: yuck COMMAND [ARG]... Generate command line option parsers for umbrella commands. -k, --keep Keep intermediary files. -o, --output=FILE Output goes into FILE instead of stdout. ## Usages of the single commands Usage: yuck [OPTION]... gen [FILE]... Generate a parser from definitions in FILE, or stdin if omitted. -H, --header=FILE Also generate a header file. --no-auto-flags Do not add auto flags (--help, --version). --no-auto-actions Do not automatically handle auto flags. --version=VERSION Hardwire version number. --custom=FILE Include custom macros from FILE. ## GENMAN Usage: yuck [OPTION]... genman [FILE]... Generate a man page from definitions in FILE, or stdin if omitted. --version-string=STRING Hardwire version number as STRING. --version-file=FILE Hardwire version number from FILE. --package=STRING Use package STRING instead of umbrella. -i, --include=FILE... Include sections from FILE --info-page[=NAME] Include reference to Texinfo manual. ## GENDSL Usage: yuck gendsl [FILE]... Generate the intermediary description of definitions from FILE, or stdin if omitted. --no-auto-flags Do not add auto flags (--help, --version). --no-auto-actions Do not automatically handle auto flags. --version=VERSION Hardwire version number. ## VER Usage: yuck scmver [PATH] Guess version number for SCM controlled PATH. If PATH is a file run a transformation. If PATH is a directory just output the version number. Transformations are done through the m4 processor: YUCK_SCMVER_VTAG will expand to the tag name. YUCK_SCMVER_SCM will expand to the name of the SCM used. YUCK_SCMVER_DIST will expand to the distance, that is the number of commits since the last tag. YUCK_SCMVER_RVSN will expand to the current commit number. YUCK_SCMVER_FLAG_DIRTY is set for changes in the source tree that have not yet been committed. Definitions in the template yuck-scmver.m4 are prepended, and by default this defines the YUCK_SCMVER_VERSION macro that expands to the full version number. -v, --verbose Print additional information on stderr. --reference=FILE Store version reference in FILE and don't touch the output file if nothing has changed. -f, --force Force operation even if the current scm version coincides with the reference version. -n, --use-reference Use version number provided in the reference file instead of determining it. --ignore-noscm Don't treat no scm as error. Usage: yuck config Output config values for yuck. --m4 Print m4 value used during yuck build. dateutils-0.4.5/configure.ac000066400000000000000000000165541335042257000160200ustar00rootroot00000000000000dnl ------------------------------------------------------------------------- dnl Autoconf startup. dnl ------------------------------------------------------------------------- AC_PREREQ([2.63]) AC_INIT([dateutils], [0.4.5], [https://github.com/hroptatyr/dateutils/issues]) AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_HEADER([src/config.h]) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_SRCDIR([src/]) dnl ------------------------------------------------------------------------- dnl Local copyright notices. dnl ------------------------------------------------------------------------- AC_COPYRIGHT([dnl #### Configuration script for dateutils and friends. #### Copyright (C) 2011-2018 Sebastian Freundt ### Don't edit this script! ### This script was automatically generated by the `autoconf' program ### from the file `./configure.ac'. ### To rebuild it, execute the command ### autoreconf ]) AM_INIT_AUTOMAKE([foreign dist-xz color-tests parallel-tests subdir-objects]) m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) ## the build chain AC_PROG_CC([icc gcc tcc cc]) SXE_CHECK_CC([gnu11 c11 gnu1x c1x gnu99 c99]) AC_C_BIGENDIAN SXE_CHECK_CFLAGS ## check/generate version files AX_YUCK_SCMVER([version.mk]) AC_CONFIG_LINKS([GNUmakefile:GNUmakefile]) ## check for clitosis helper AX_CHECK_CLITOSIS ## check for byteorder utils AC_CHECK_HEADERS([endian.h sys/endian.h machine/endian.h byteorder.h]) AC_CHECK_HEADERS([byteswap.h]) AC_CHECK_HEADERS([sys/param.h]) AC_CHECK_HEADERS([sys/types.h]) ## to make lintian happy AC_SYS_LARGEFILE ## check for mmap and friends SXE_CHECK_MMAP ## for getline()/fgetln() code (e.g. tzmap.c) AC_CHECK_FUNCS([getline]) AC_CHECK_FUNCS([fgetln]) ## AIX' take on stdint AC_CHECK_HEADERS([sys/stdint.h]) ## check for tzfile.h AX_ZONEINFO([right]) AM_CONDITIONAL([ZONEINFO_UTC_RIGHT], [test -n "${ax_cv_zoneinfo_utc_right}"]) ## check for strptime AC_CHECK_FUNCS([strptime]) have_strptime="${ac_cv_func_strptime}" AM_CONDITIONAL([HAVE_STRPTIME], [test "${have_strptime}" = "yes"]) ## check for working c1x features SXE_CHECK_ANON_STRUCTS_DECL SXE_CHECK_ANON_STRUCTS_INIT SXE_CHECK_SLOPPY_STRUCTS_INIT if test "${sxe_cv_have_anon_structs_decl}" != "yes"; then AC_MSG_ERROR([C compiler unusable dateutils make extensive use of c11 anonymous structs/unions but your compiler does not fully support them. Change either the CFLAGS or the compiler. Good day. ]) fi AM_PROG_LEX AC_PROG_YACC AC_PATH_PROG([GPERF], [gperf]) if test -z "${GPERF}"; then GPERF="gperf" fi AC_ARG_VAR([GPERF], [full path to the gperf tool]) ## check if we've got curl, necessary to d/l the tzmaps AC_PATH_PROG([CURL], [curl]) AC_ARG_VAR([CURL], [full path to the curl tool]) AM_CONDITIONAL([HAVE_CURL], [test -n "${CURL}"]) AC_ARG_ENABLE([tzmap-fetch], [ AS_HELP_STRING([--enable-tzmap-fetch], [Fetch tzmaps from github, default: no.])], [dnl enable_tzmap_fetch="${enableval}" if test -z "${CURL}"; then enable_tzmap_fetch="no" fi ], [enable_tzmap_fetch="no"]) AM_CONDITIONAL([FETCH_TZMAPS], [test "${enable_tzmap_fetch}" = "yes"]) AM_CONDITIONAL([HAVE_TZMAPS], [test `find "${srcdir}/lib" -name '*.tzmap' -print | wc -l` -gt 0]) AC_PATH_PROG([GDATE], [date]) AC_ARG_VAR([GDATE], [full path to the date tool]) if test -n "${GDATE}"; then ## try and use -d AC_MSG_CHECKING([if date is of GNU flavour]) if "${GDATE}" -d "2012-01-01" >/dev/null 2>/dev/null; then have_gdate="yes" else have_gdate="no" fi AC_MSG_RESULT([${have_gdate}]) fi if test -n "${GDATE}" -a "${have_gdate}" = "yes"; then ## try and use -d with a big year AC_MSG_CHECKING([if date is immune to year 2038 problem]) if "${GDATE}" -d "4095-01-01" >/dev/null 2>/dev/null; then have_gdate_2039="yes" else have_gdate_2039="no" fi AC_MSG_RESULT([${have_gdate_2039}]) fi AC_ARG_VAR([have_gdate], [yes if GDATE is of GNU flavour]) AC_ARG_VAR([have_gdate_2039], [yes if GDATE can handle years beyond 2038]) AM_CONDITIONAL([HAVE_GDATE], [test "${have_gdate}" = "yes"]) AM_CONDITIONAL([HAVE_GDATE_2039], [test "${have_gdate_2039}" = "yes"]) AC_ARG_ENABLE([fast-arith], [AS_HELP_STRING([--enable-fast-arith], [ Whether to enable fast date handling and arithmetic routines at the cost of strictness. For instance the leap year rule used is incorrect for years before 1901 and after 2100, or every month can have a 31st to denote the last day of the month.]) AS_HELP_STRING([], [Default: disabled])], [enable_fast_arith="${enableval}"], [enable_fast_arith="no"]) AC_ARG_ENABLE([contrib], [ AS_HELP_STRING([--enable-contrib], [Build contribs, default: no.])], [enable_contrib="${enableval}"], [enable_contrib="no"]) AM_CONDITIONAL([WITH_CONTRIB], [test "${enable_contrib}" != "no"]) AC_ARG_WITH([old-names], [ AS_HELP_STRING([--with-old-names], [Install old binary names only, default: no.])], [with_old_names="${withval}"], [with_old_names="no"]) AM_CONDITIONAL([WITH_OLD_NAMES], [test "${with_old_names}" != "no"]) AC_ARG_WITH([old-links], [ AS_HELP_STRING([--with-old-links], [Install compatibility symlinks, default: yes.])], [with_old_links="${withval}"], [with_old_links="yes"]) AM_CONDITIONAL([WITH_OLD_LINKS], [test "${with_old_links}" != "no"]) ## checks if test "${enable_fast_arith}" = "yes"; then AC_DEFINE([WITH_FAST_ARITH], [1], [whether to use fast but incorrect date routines]) fi ## always define this one for now AC_DEFINE([WITH_LEAP_SECONDS], [1], [Whether to use leap-second aware routines]) AM_CONDITIONAL([WITH_LEAP_SECONDS], [test "1" = "1"]) ## trivial conditional so that the dexpr scanner and parser are built AM_CONDITIONAL([BUILD_DEXPR], [test "0" = "1"]) AM_CONDITIONAL([BUILD_LTRCC], [test ! -f "${srcdir}/lib/leapseconds.def"]) ## check for contrib stuff if test "${enable_contrib}" != "no"; then ## check for matlab, then octave SXE_CHECK_MATLAB SXE_CHECK_OCTAVE fi AM_CONDITIONAL([BUILD_MEXCLI], [test "${sxe_cv_matlab_mex_h}" = "yes" -a -n "${MATLABPATH}"]) AM_CONDITIONAL([BUILD_OCTCLI], [test "${sxe_cv_octave_mex_h}" = "yes" -a -n "${OCTAVEPATH}"]) ## prepare the summary page if test "${with_old_names}" = "no"; then dut_apps="dateadd dateconv datediff dategrep dateround dateseq datesort datetest datezone" else dut_apps="dadd dconv ddiff dgrep dround dseq dsort dtest dzone" fi if test "${have_strptime}" = "yes"; then misc_apps="strptime" else misc_apps="none" fi if test "${enable_contrib}" != "no"; then if test "${sxe_cv_matlab_mex_h}" = "yes"; then cntrb_apps="${cntrb_apps}${cntrb_apps:+ }tzconv.m(atlab)" fi if test "${sxe_cv_octave_mex_h}" = "yes"; then cntrb_apps="${cntrb_apps}${cntrb_apps:+ }tzconv.m(octave)" fi else cntrb_apps="none" fi AX_CHECK_YUCK dnl must come after all AC_LINK_IFELSE clauses ## check for the ldflags SXE_CHECK_LDFLAGS LT_INIT SXE_CHECK_LIBTOOL AC_CONFIG_FILES([Makefile]) AC_CONFIG_FILES([build-aux/Makefile]) AC_CONFIG_FILES([data/Makefile]) AC_CONFIG_FILES([lib/Makefile]) AC_CONFIG_FILES([src/Makefile]) AC_CONFIG_FILES([info/Makefile]) AC_CONFIG_FILES([test/Makefile]) AC_CONFIG_FILES([contrib/Makefile]) AC_OUTPUT cat < * * This file is part of dateutils. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***/ #if defined HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include #include #include /* matlab stuff */ #if defined HAVE_OCTAVE_MEX_H # include #else /* !HAVE_OCTAVE_MEX_H */ # include #endif /* HAVE_OCTAVE_MEX_H */ /* our stuff */ #include "tzraw.h" /* see tzconv.m for details */ static zif_t find_zone(const mxArray *zstr) { char *zone = mxArrayToString(zstr); zif_t res; res = zif_open(zone); if (zone != NULL) { mxFree(zone); } return res; } void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { zif_t fromz; zif_t toz; if (nrhs != 3 || nlhs > 1) { mexErrMsgTxt("invalid usage, see `help tzconv'\n"); return; } /* find zones */ if ((fromz = find_zone(prhs[1])) == NULL) { mexErrMsgTxt("cannot open from zone\n"); } if ((toz = find_zone(prhs[2])) == NULL) { zif_close(fromz); mexErrMsgTxt("cannot open target zone\n"); } #define TO_UNIX(x) ((x) - 719529.0) * 86400.0 #define TO_MATL(x) ((x) / 86400.0) + 719529.0 { mwSize m = mxGetM(prhs[0]); mwSize n = mxGetN(prhs[0]); const double *src = mxGetPr(prhs[0]); double *tgt; plhs[0] = mxCreateDoubleMatrix(m, n, mxREAL); tgt = mxGetPr(plhs[0]); for (mwSize i = 0; i < m * n; i++) { double x = TO_UNIX(src[i]); if (x < 2147483647.0 && x > -2147483648.0) { double frac = modf(x, &x); int32_t utc = zif_utc_time(fromz, (int32_t)x); int32_t lcl = zif_local_time(toz, utc); tgt[i] = TO_MATL((double)lcl) + frac / 86400.0; } else { tgt[i] = NAN; } } } zif_close(fromz); zif_close(toz); return; } /* gand_get_series.c ends here */ dateutils-0.4.5/contrib/tzconv.m000066400000000000000000000006571335042257000166700ustar00rootroot00000000000000% tzconv convert between timezones % % Syntax: % d = tzconv(dates, from_zone, to_zone); % % Input Arguments: % dates - a vector of matlab dates to be converted % from_zone - interpret DATES as coming from FROM_ZONE % to_zone - convert DATEs to TO_ZONE % % Output Arguments: % d - vector of dates in the result % % Copyright (C) 2013 Sebastian Freundt % % This file is part of dateutils dateutils-0.4.5/data/000077500000000000000000000000001335042257000144305ustar00rootroot00000000000000dateutils-0.4.5/data/Makefile.am000066400000000000000000000005701335042257000164660ustar00rootroot00000000000000### Makefile.am include $(top_builddir)/version.mk AM_CFLAGS = $(EXTRA_CFLAGS) AM_CPPFLAGS = -D_POSIX_C_SOURCE=200112L -D_XOPEN_SOURCE=600 -D_BSD_SOURCE AM_LDFLAGS = bin_PROGRAMS = noinst_PROGRAMS = noinst_HEADERS = noinst_LIBRARIES = pkgdata_DATA = BUILT_SOURCES = CLEANFILES = GGO_HELPERS = EXTRA_DIST = $(BUILT_SOURCES) $(pkgdata_DATA) SUFFIXES = pkgdata_DATA += locale dateutils-0.4.5/data/locale000066400000000000000000002553051335042257000156240ustar00rootroot00000000000000aa_DJ etl tal arb kam gum sab aca Etleeni Talaata Arbaqa Kamiisi Gumqata Sabti Acaada qun nah cig agd cax qas qad leq way dit xim kax Qunxa Garablu Kudo Ciggilta Kudo Agda Baxisso Caxah Alsa Qasa Dirri Qado Dirri Liiqen Waysu Diteli Ximoli Kaxxa Garablu aa_ER Etl Tal Arb Kam Gum Sab Aca Etleeni Talaata Arbaqa Kamiisi Gumqata Sabti Acaada Qun Nah Cig Agd Cax Qas Qad Leq Way Dit Xim Kax Qunxa Garablu Naharsi Kudo Ciggilta Kudo Agda Baxisso Caxah Alsa Qasa Dirri Qado Dirri Leqeeni Waysu Diteli Ximoli Kaxxa Garablu aa_ET Etl Tal Arb Kam Gum Sab Aca Etleeni Talaata Arbaqa Kamiisi Gumqata Sabti Acaada Qun Kud Cig Agd Cax Qas Qad Leq Way Dit Xim Kax Qunxa Garablu Kudo Ciggilta Kudo Agda Baxisso Caxah Alsa Qasa Dirri Qado Dirri Liiqen Waysu Diteli Ximoli Kaxxa Garablu af_ZA Ma Di Wo Do Vr Sa So Maandag Dinsdag Woensdag Donderdag Vrydag Saterdag Sondag Jan Feb Mrt Apr Mei Jun Jul Aug Sep Okt Nov Des Januarie Februarie Maart April Mei Junie Julie Augustus September Oktober November Desember ak_GH Mon Tue Wed Thu Fri Sat Sun Monday Tuesday Wednesday Thursday Friday Saturday Sunday Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec January February March April May June July August September October November December am_ET ሰኞ ማክሰ ረቡዕ ሐሙስ ዓርብ ቅዳሜ እሑድ ሰኞ ማክሰኞ ረቡዕ ሐሙስ ዓርብ ቅዳሜ እሑድ ጃንዩ ፌብሩ ማርች ኤፕረ ሜይ ጁን ጁላይ ኦገስ ሴፕቴ ኦክተ ኖቬም ዲሴም ጃንዩወሪ ፌብሩወሪ ማርች ኤፕረል ሜይ ጁን ጁላይ ኦገስት ሴፕቴምበር ኦክተውበር ኖቬምበር ዲሴምበር an_ES lun mar mie chu bie sab dom luns martes miecols chuebes biernes sabado domingo chi fre mar abr may chn chl ago set oct nob abi chinero frebero marzo abril mayo chunio chulio agosto setiembre octubre nobiembre abiento anp_IN Mon Tue Wed Thu Fri Sat Sun Monday Tuesday Wednesday Thursday Friday Saturday Sunday Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec January February March April May June July August September October November December ar_AE ن ث ر خ ج س ح الاثنين الثلاثاء الأربعاء الخميس الجمعة السبت الأحد ينا فبر مار أبر ماي يون يول أغس سبت أكت نوف ديس يناير فبراير مارس أبريل مايو يونيو يوليو أغسطس سبتمبر أكتوبر نوفمبر ديسمبر ar_BH ن ث ر خ ج س ح الاثنين الثلاثاء الأربعاء الخميس الجمعة السبت الأحد ينا فبر مار أبر ماي يون يول أغس سبت أكت نوف ديس يناير فبراير مارس أبريل مايو يونيو يوليو أغسطس سبتمبر أكتوبر نوفمبر ديسمبر ar_DZ ن ث ر خ ج س ح الاثنين الثلاثاء الأربعاء الخميس الجمعة السبت الأحد ينا فبر مار أبر ماي يون يول أغس سبت أكت نوف ديس يناير فبراير مارس أبريل مايو يونيو يوليو أغسطس سبتمبر أكتوبر نوفمبر ديسمبر ar_EG ن ث ر خ ج س ح الاثنين الثلاثاء الأربعاء الخميس الجمعة السبت الأحد ينا فبر مار أبر ماي يون يول أغس سبت أكت نوف ديس يناير فبراير مارس أبريل مايو يونيو يوليو أغسطس سبتمبر أكتوبر نوفمبر ديسمبر ar_IN ن ث ر خ ج س ح الاثنين الثلاثاء الأربعاء الخميس الجمعة السبت الأحد ينا فبر مار أبر ماي يون يول أغس سبت أكت نوف ديس يناير فبراير مارس أبريل مايو يونيو يوليو أغسطس سبتمبر أكتوبر نوفمبر ديسمبر ar_IQ ن ث ر خ ج س ح الاثنين الثلاثاء الأربعاء الخميس الجمعة السبت الأحد ينا فبر مار أبر ماي يون يول أغس سبت أكت نوف ديس يناير فبراير مارس أبريل مايو يونيو يوليو أغسطس سبتمبر أكتوبر نوفمبر ديسمبر ar_JO الاثنين الثلاثاء الأربعاء الخميس الجمعة السبت الأحد الاثنين الثلاثاء الأربعاء الخميس الجمعة السبت الأحد كانون الثاني شباط آذار نيسان نوار حزيران تموز آب أيلول تشرين الأول تشرين الثاني كانون الأول كانون الثاني شباط آذار نيسان نوار حزيران تموز آب أيلول تشرين الأول تشرين الثاني كانون الأول ar_KW ن ث ر خ ج س ح الاثنين الثلاثاء الأربعاء الخميس الجمعة السبت الأحد ينا فبر مار أبر ماي يون يول أغس سبت أكت نوف ديس يناير فبراير مارس أبريل مايو يونيو يوليو أغسطس سبتمبر أكتوبر نوفمبر ديسمبر ar_LB الاثنين الثلاثاء الأربعاء الخميس الجمعة السبت الأحد الاثنين الثلاثاء الأربعاء الخميس الجمعة السبت الأحد كانون الثاني شباط آذار نيسان نوار حزيران تموز آب أيلول تشرين الأول تشرين الثاني كانون الأول كانون الثاني شباط آذار نيسان نوار حزيران تموز آب أيلول تشرين الأول تشرين الثاني كانون الأول ar_LY ن ث ر خ ج س ح الاثنين الثلاثاء الأربعاء الخميس الجمعة السبت الأحد ينا فبر مار أبر ماي يون يول أغس سبت أكت نوف ديس يناير فبراير مارس أبريل مايو يونيو يوليو أغسطس سبتمبر أكتوبر نوفمبر ديسمبر ar_MA ن ث ر خ ج س ح الاثنين الثلاثاء الأربعاء الخميس الجمعة السبت الأحد ينا فبر مار أبر ماي يون يول أغس سبت أكت نوف ديس يناير فبراير مارس أبريل مايو يونيو يوليو أغسطس سبتمبر أكتوبر نوفمبر ديسمبر ar_OM ن ث ر خ ج س ح الاثنين الثلاثاء الأربعاء الخميس الجمعة السبت الأحد ينا فبر مار أبر ماي يون يول أغس سبت أكت نوف ديس يناير فبراير مارس أبريل مايو يونيو يوليو أغسطس سبتمبر أكتوبر نوفمبر ديسمبر ar_QA ن ث ر خ ج س ح الاثنين الثلاثاء الأربعاء الخميس الجمعة السبت الأحد ينا فبر مار أبر ماي يون يول أغس سبت أكت نوف ديس يناير فبراير مارس أبريل مايو يونيو يوليو أغسطس سبتمبر أكتوبر نوفمبر ديسمبر ar_SA Mon Tue Wed Thu Fri Sat Sun الإثنين الثلاثاء الأربعاء الخميس الجمعـة السبت الأحد Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec كانون الثاني شباط آذار نيسـان أيار حزيران تـمـوز آب أيلول تشرين الأول تشرين الثاني كانون الأول ar_SD ن ث ر خ ج س ح الاثنين الثلاثاء الأربعاء الخميس الجمعة السبت الأحد ينا فبر مار أبر ماي يون يول أغس سبت أكت نوف ديس يناير فبراير مارس أبريل مايو يونيو يوليو أغسطس سبتمبر أكتوبر نوفمبر ديسمبر ar_SS Mon Tue Wed Thu Fri Sat Sun Monday Tuesday Wednesday Thursday Friday Saturday Sunday Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec January February March April May June July August September October November December ar_SY الاثنين الثلاثاء الأربعاء الخميس الجمعة السبت الأحد الاثنين الثلاثاء الأربعاء الخميس الجمعة السبت الأحد كانون الثاني شباط آذار نيسان نوار حزيران تموز آب أيلول تشرين الأول تشرين الثاني كانون الأول كانون الثاني شباط آذار نيسان نواران حزير تموز آب أيلول تشرين الأول تشرين الثاني كانون الأول ar_TN ن ث ر خ ج س ح الاثنين الثلاثاء الأربعاء الخميس الجمعة السبت الأحد ينا فبر مار أبر ماي يون يول أغس سبت أكت نوف ديس يناير فبراير مارس أبريل مايو يونيو يوليو أغسطس سبتمبر أكتوبر نوفمبر ديسمبر ar_YE ن ث ر خ ج س ح الاثنين الثلاثاء الأربعاء الخميس الجمعة السبت الأحد ينا فبر مار أبر ماي يون يول أغس سبت أكت نوف ديس يناير فبراير مارس أبريل مايو يونيو يوليو أغسطس سبتمبر أكتوبر نوفمبر ديسمبر as_IN সোম মঙ্গল বুধ বৃহষ্পতি শুক্ৰ শনি দেও সোমবাৰ মঙ্গলবাৰ বুধবাৰ বৃহষ্পতিবাৰ শুক্ৰবাৰ শনিবাৰ দেওবাৰ জানুৱাৰী ফেব্ৰুৱাৰী মাৰ্চ এপ্ৰিল মে জুন জুলাই আগ চেপ্তেম্বৰ অক্টোবৰ নভেম্বৰ ডিচেম্বৰ জানুৱাৰী ফেব্ৰুৱাৰী মাৰ্চ এপ্ৰিল মে জুন জুলাই আগষ্ট চেপ্তেম্বৰ অক্টোবৰ নভেম্বৰ ডিচেম্বৰ ast_ES llu mar mié xue vie sáb dom llunes martes miércoles xueves vienres sábadu domingu xin feb mar abr may xun xnt ago set och pay avi xineru febreru marzu abril mayu xunu xunetu agostu setiembre ochobre payares avientu ayc_PE lun mar mir juy wir saw tum lunisa martisa mirkulisa juywisa wirnisa sawäru tuminku ini phi mar awr may jun jul awu sit ukt nuw ris inïru phiwriru marsu awrila mayu junyu julyu awustu sitimri uktuwri nuwimri risimri az_AZ ber çax çər cax cüm şnb baz bazar ertəsi çərşənbə axşamı çərşənbə cümə axşamı cümə şənbə bazar günü Yan Fev Mar Apr May İyn İyl Avq Sen Okt Noy Dek yanvar fevral mart aprel may iyun iyul avqust sentyabr oktyabr noyabr dekabr be_BY Пан Аўт Срд Чцв Пят Суб Няд Панядзелак Аўторак Серада Чацвер Пятніца Субота Нядзеля Стд Лют Сак Крс Тра Чэр Ліп Жнв Врс Кст Ліс Снж Студзень Люты Сакавік Красавік Травень Чэрвень Ліпень Жнівень Верасень Кастрычнік Лістапад Снежань bem_ZM Mon Tue Wed Thu Fri Sat Sun Palichimo Palichibuli Palichitatu Palichine Palichisano Pachibelushi Pa Mulungu Jan Feb Mar Apr May Jun July Aug Sep Oct Nov Dec Januari Februari Machi Epreo Mei Juni Julai Ogasti Septemba Oktoba Novemba Disemba ber_DZ bir iki üçü dör beş alt baz birinci gün ikinci gün üçüncü gün dördüncü gün beşinci gün altıncı gün bazar günü Yan Fev Mar Apr May İyn İyl Avq Sen Okt Noy Dek yanvar fevral mart aprel may iyun iyul avqust sentyabr oktyabr noyabr dekabr ber_MA bir iki üçü dör beş alt baz birinci gün ikinci gün üçüncü gün dördüncü gün beşinci gün altıncı gün bazar günü Yan Fev Mar Apr May İyn İyl Avq Sen Okt Noy Dek yanvar fevral mart aprel may iyun iyul avqust sentyabr oktyabr noyabr dekabr bg_BG пн вт ср чт пт сб нд понеделник вторник сряда четвъртък петък събота неделя яну фев мар апр май юни юли авг сеп окт ное дек януари февруари март април май юни юли август септември октомври ноември декември bho_IN सोम मंगल बुध गुरु शुक्र शनि रवि सोमवार मंगलवार बुधवार गुरुवार शुक्रवार शनिवार रविवार जनवरी फरवरी मार्च अप्रैल मई जून जुलाई अगस्त सितम्बर अक्टूबर नवम्बर दिसम्बर जनवरी फरवरी मार्च अप्रैल मई जून जुलाई अगस्त सितम्बर अक्टूबर नवम्बर दिसम्बर bn_BD সোম মঙ্গল বুধ বৃহঃ শুক্র শনি রবি সোমবার মঙ্গলবার বুধবার বৃহস্পতিবার শুক্রবার শনিবার রবিবার জানু ফেব্রু মার্চ এপ্রি মে জুন জুল আগ সেপ্টে অক্টো নভে ডিসে জানুয়ারি ফেব্রুয়ারি মার্চ এপ্রিল মে জুন জুলাই আগস্ট সেপ্টেম্বর অক্টোবর নভেম্বর ডিসেম্বর bn_IN সোম মঙ্গল বুধ বৃহস্পতি শুক্র শনি রবি সোমবার মঙ্গলবার বুধবার বৃহস্পতিবার শুক্রবার শনিবার রবিবার জানুয়ারি ফেব্রুয়ারি মার্চ এপ্রিল মে জুন জুলাই আগস্ট সেপ্টেম্বর অক্টোবর নভেম্বর ডিসেম্বর জানুয়ারি ফেব্রুয়ারি মার্চ এপ্রিল মে জুন জুলাই আগস্ট সেপ্টেম্বর অক্টোবর নভেম্বর ডিসেম্বর bo_CN ཟླ་ མིར་ ལྷག་ པུར་ སངས་ སྤེན་ ཉི་ གཟའ་ཟླ་བ་ གཟའ་མིག་དམར་ གཟའ་ལྷག་ཕ་ གཟའ་པུར་བུ་ གཟའ་པ་སངས་ གཟའ་སྤེན་ཕ་ གཟའ་ཉི་མ་ ཟླ་༡ ཟླ་༢ ཟླ་༣ ཟླ་༤ ཟླ་༥ ཟླ་༦ ཟླ་༧ ཟླ་༨ ཟླ་༩ ཟླ་༡༠ ཟླ་༡༡ ཟླ་༡༢ ཟླ་བ་དང་པ་ ཟླ་བ་གཉིས་པ་ ཟླ་བ་གསུམ་པ་ ཟླ་བ་བཞི་པ་ ཟླ་བ་ལྔ་ཕ་ ཟླ་བ་དྲུག་པ་ ཟླ་བ་བདུནཔ་ ཟླ་བ་བརྒྱད་པ་ ཟླ་བ་དགུ་པ་ ཟླ་བ་བཅུ་པ་ ཟླ་བ་བཅུ་གཅིག་པ་ ཟླ་བ་བཅུ་གཉིས་པ་ bo_IN ཟླ་ མིར་ ལྷག་ པུར་ སངས་ སྤེན་ ཉི་ གཟའ་ཟླ་བ་ གཟའ་མིག་དམར་ གཟའ་ལྷག་ཕ་ གཟའ་པུར་བུ་ གཟའ་པ་སངས་ གཟའ་སྤེན་ཕ་ གཟའ་ཉི་མ་ ཟླ་༡ ཟླ་༢ ཟླ་༣ ཟླ་༤ ཟླ་༥ ཟླ་༦ ཟླ་༧ ཟླ་༨ ཟླ་༩ ཟླ་༡༠ ཟླ་༡༡ ཟླ་༡༢ ཟླ་བ་དང་པ་ ཟླ་བ་གཉིས་པ་ ཟླ་བ་གསུམ་པ་ ཟླ་བ་བཞི་པ་ ཟླ་བ་ལྔ་ཕ་ ཟླ་བ་དྲུག་པ་ ཟླ་བ་བདུནཔ་ ཟླ་བ་བརྒྱད་པ་ ཟླ་བ་དགུ་པ་ ཟླ་བ་བཅུ་པ་ ཟླ་བ་བཅུ་གཅིག་པ་ ཟླ་བ་བཅུ་གཉིས་པ་ br_FR lun meu mer yao gwe sad sul lun meurzh merc'her yaou gwener sadorn sul Gen C'hw Meu Ebr Mae Eve Gou Eos Gwe Her Du Ker Genver C'hwevrer Meurzh Ebrel Mae Mezheven Gouere Eost Gwengolo Here Du Kerzu brx_IN सम मंगल बुद बिसथि सुखुर सुनि रबि सोबार मंगलबार बुदबार बिसथिबार सुखुरबार सुनिबार रबिबार जानुवारी फेब्रुवारी मार्स एप्रिल मे जुन जुलाइ आगस्थ सेबथेज्ब़र अखथबर नबेज्ब़र दिसेज्ब़र जानुवारी फेब्रुवारी मार्स एप्रिल मे जुन जुलाइ आगस्थ सेबथेज्ब़र अखथबर नबेज्ब़र दिसेज्ब़र bs_BA Pon Uto Sri Čet Pet Sub Ned Ponedjeljak Utorak Srijeda Četvrtak Petak Subota Nedjelja Jan Feb Mar Apr Maj Jun Jul Aug Sep Okt Nov Dec Januar Februar Mart April Maj Juni Juli August Septembar Oktobar Novembar Decembar byn_ER ሰኑ ሰሊጝ ለጓ ኣምድ ኣርብ ሰ/ሽ ሰ/ቅ ሰኑ ሰሊጝ ለጓ ወሪ ለብዋ ኣምድ ኣርብ ሰንበር ሽጓዅ ሰንበር ቅዳዅ ልደት ካብኽ ክብላ ፋጅኺ ክቢቅ ም/ት ኰር ማርያ ያኸኒ መተሉ ም/ም ተሕሳ ልደትሪ ካብኽብቲ ክብላ ፋጅኺሪ ክቢቅሪ ምኪኤል ትጓ̅ኒሪ ኰርኩ ማርያም ትሪ ያኸኒ መሳቅለሪ መተሉ ምኪኤል መሽወሪ ተሕሳስሪ ca_AD dl dt dc dj dv ds dg dilluns dimarts dimecres dijous divendres dissabte diumenge gen feb mar abr mai jun jul ago set oct nov des gener febrer març abril maig juny juliol agost setembre octubre novembre desembre ca_ES dl dt dc dj dv ds dg dilluns dimarts dimecres dijous divendres dissabte diumenge gen feb mar abr mai jun jul ago set oct nov des gener febrer març abril maig juny juliol agost setembre octubre novembre desembre ca_FR dl dt dc dj dv ds dg dilluns dimarts dimecres dijous divendres dissabte diumenge gen feb mar abr mai jun jul ago set oct nov des gener febrer març abril maig juny juliol agost setembre octubre novembre desembre ca_IT dl dt dc dj dv ds dg dilluns dimarts dimecres dijous divendres dissabte diumenge gen feb mar abr mai jun jul ago set oct nov des gener febrer març abril maig juny juliol agost setembre octubre novembre desembre cmn_TW Mon Tue Wed Thu Fri Sat Sun Monday Tuesday Wednesday Thursday Friday Saturday Sunday Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec January February March April May June July August September October November December crh_UA Ber Sal Çar Caq Cum Cer Baz Bazarertesi Salı Çarşembe Cumaaqşamı Cuma Cumaertesi Bazar Yan Fev Mar Apr May İyn İyl Avg Sen Okt Noy Dek Yanvar Fevral Mart Aprel Mayıs İyun İyul Avgust Sentâbr Oktâbr Noyabr Dekabr cs_CZ Po Út St Čt Pá So Ne Pondělí Úterý Středa Čtvrtek Pátek Sobota Neděle led úno bře dub kvě čen čec srp zář říj lis pro leden únor březen duben květen červen červenec srpen září říjen listopad prosinec csb_PL pòn wtó str czw pią sob nie pòniedzôłk wtórk strzoda czwiôrtk piątk sobòta niedzela stë gro stm łżë môj cze lëp zél séw ruj lës gòd stëcznik gromicznik strumiannik łżëkwiôt môj czerwińc lëpinc zélnik séwnik rujan lëstopadnik gòdnik cv_RU tn yt jn kş er šm vr tuntikun ytlarikun junkun kĕşnernikun ernekun šămatkun vyrsarnikun KĂR NAR PUŠ AKA ŞU ŞĔR UTĂ ŞUR AVĂ JUP CÜK RAŠ kărlac narăs puš aka şu şĕrtme ută şurla avăn jupa cük raštav cy_GB Llu Maw Mer Iau Gwe Sad Sul Llun Mawrth Mercher Iau Gwener Sadwrn Sul Ion Chw Maw Ebr Mai Meh Gor Aws Med Hyd Tach Rha Ionawr Chwefror Mawrth Ebrill Mai Mehefin Gorffennaf Awst Medi Hydref Tachwedd Rhagfyr da_DK man tir ons tor fre lør søn mandag tirsdag onsdag torsdag fredag lørdag søndag jan feb mar apr maj jun jul aug sep okt nov dec januar februar marts april maj juni juli august september oktober november december de_AT Mon Die Mit Don Fre Sam Son Montag Dienstag Mittwoch Donnerstag Freitag Samstag Sonntag Jän Feb Mär Apr Mai Jun Jul Aug Sep Okt Nov Dez Jänner Februar März April Mai Juni Juli August September Oktober November Dezember de_BE Mon Die Mit Don Fre Sam Son Montag Dienstag Mittwoch Donnerstag Freitag Samstag Sonntag Jan Feb Mär Apr Mai Jun Jul Aug Sep Okt Nov Dez Januar Februar März April Mai Juni Juli August September Oktober November Dezember de_CH Mon Die Mit Don Fre Sam Son Montag Dienstag Mittwoch Donnerstag Freitag Samstag Sonntag Jan Feb Mär Apr Mai Jun Jul Aug Sep Okt Nov Dez Januar Februar März April Mai Juni Juli August September Oktober November Dezember de_DE Mo Di Mi Do Fr Sa So Montag Dienstag Mittwoch Donnerstag Freitag Samstag Sonntag Jan Feb Mär Apr Mai Jun Jul Aug Sep Okt Nov Dez Januar Februar März April Mai Juni Juli August September Oktober November Dezember de_LU Mon Die Mit Don Fre Sam Son Montag Dienstag Mittwoch Donnerstag Freitag Samstag Sonntag Jan Feb Mär Apr Mai Jun Jul Aug Sep Okt Nov Dez Januar Februar März April Mai Juni Juli August September Oktober November Dezember doi_IN सोम मंगल बुध बीर शुक्कर श्नीचर ऐत सोमबार मंगलबर बुधबार बीरबार शुक्करबार श्नीचरबार ऐतबार जनवरी फरवरी मार्च एप्रैल मेई जून जूलै अगस्त सितंबर अक्तूबर नवंबर दिसंबर जनवरी फरवरी मार्च एप्रैल मेई जून जूलै अगस्त सितंबर अक्तूबर नवंबर दिसंबर dv_MV ހޯމަ އަންގާރަ ބުދަ ބުރާސްފަތި ހުކުރު ހޮނިހިރު އާދީއްތަ ހޯމަ އަންގާރަ ބުދަ ބުރާސްފަތި ހުކުރު ހޮނިހިރު އާދީއްތަ ޖެނުއަރީ ފެބްރުއަރީ މާރޗް އެޕްރީލް މެއި ޖޫން ޖުލައި އޮގަސްޓް ސެޕްޓެންބަރ އޮކްޓޫބަރ ނޮވެންބަރ ޑިސެންބަރ ޖެނުއަރީ ފެބްރުއަރީ މާރޗް އެޕްރީލް މެއި ޖޫން ޖުލައި އޮގަސްޓް ސެޕްޓެންބަރ އޮކްޓޫބަރ ނޮވެންބަރ ޑިސެންބަރ dz_BT མིར་ ལྷག་ པུར་ སངས་ སྤེན་ ཉི་ ཟླ་ གཟའ་མིག་དམར་ གཟའ་ལྷག་ཕ་ གཟའ་པུར་བུ་ གཟའ་པ་སངས་ གཟའ་སྤེན་ཕ་ གཟའ་ཉི་མ་ གཟའ་ཟླ་བ་ ཟླ་༡ ཟླ་༢ ཟླ་༣ ཟླ་༤ ཟླ་༥ ཟླ་༦ ཟླ་༧ ཟླ་༨ ཟླ་༩ ཟླ་༡༠ ཟླ་༡༡ ཟླ་༡༢ ཟླ་བ་དང་པ་ ཟླ་བ་གཉིས་པ་ ཟླ་བ་གསུམ་པ་ ཟླ་བ་བཞི་པ་ ཟླ་བ་ལྔ་ཕ་ ཟླ་བ་དྲུག་པ་ ཟླ་བ་བདུནཔ་ ཟླ་བ་བརྒྱད་པ་ ཟླ་བ་དགུ་པ་ ཟླ་བ་བཅུ་པ་ ཟླ་བ་བཅུ་གཅིག་པ་ ཟླ་བ་བཅུ་གཉིས་པ་ el_CY Δευ Τρι Τετ Πεμ Παρ Σαβ Κυρ Δευτέρα Τρίτη Τετάρτη Πέμπτη Παρασκευή Σάββατο Κυριακή Ιαν Φεβ Μάρ Απρ Μάι Ιούν Ιούλ Αύγ Σεπ Οκτ Νοέ Δεκ Ιανουάριος Φεβρουάριος Μάρτιος Απρίλιος Μάιος Ιούνιος Ιούλιος Αύγουστος Σεπτέμβριος Οκτώβριος Νοέμβριος Δεκέμβριος el_GR Δευ Τρι Τετ Πεμ Παρ Σαβ Κυρ Δευτέρα Τρίτη Τετάρτη Πέμπτη Παρασκευή Σάββατο Κυριακή Ιαν Φεβ Μάρ Απρ Μάι Ιούν Ιούλ Αύγ Σεπ Οκτ Νοέ Δεκ Ιανουάριος Φεβρουάριος Μάρτιος Απρίλιος Μάιος Ιούνιος Ιούλιος Αύγουστος Σεπτέμβριος Οκτώβριος Νοέμβριος Δεκέμβριος en_AG Mon Tue Wed Thu Fri Sat Sun Monday Tuesday Wednesday Thursday Friday Saturday Sunday Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec January February March April May June July August September October November December en_AU Mon Tue Wed Thu Fri Sat Sun Monday Tuesday Wednesday Thursday Friday Saturday Sunday Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec January February March April May June July August September October November December en_BW Mon Tue Wed Thu Fri Sat Sun Monday Tuesday Wednesday Thursday Friday Saturday Sunday Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec January February March April May June July August September October November December en_CA Mon Tue Wed Thu Fri Sat Sun Monday Tuesday Wednesday Thursday Friday Saturday Sunday Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec January February March April May June July August September October November December en_DK Mon Tue Wed Thu Fri Sat Sun Monday Tuesday Wednesday Thursday Friday Saturday Sunday Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec January February March April May June July August September October November December en_GB Mon Tue Wed Thu Fri Sat Sun Monday Tuesday Wednesday Thursday Friday Saturday Sunday Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec January February March April May June July August September October November December en_HK Mon Tue Wed Thu Fri Sat Sun Monday Tuesday Wednesday Thursday Friday Saturday Sunday Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec January February March April May June July August September October November December en_IE Mon Tue Wed Thu Fri Sat Sun Monday Tuesday Wednesday Thursday Friday Saturday Sunday Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec January February March April May June July August September October November December en_IN Mon Tue Wed Thu Fri Sat Sun Monday Tuesday Wednesday Thursday Friday Saturday Sunday Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec January February March April May June July August September October November December en_NG Mon Tue Wed Thu Fri Sat Sun Monday Tuesday Wednesday Thursday Friday Saturday Sunday Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec January February March April May June July August September October November December en_NZ Mon Tue Wed Thu Fri Sat Sun Monday Tuesday Wednesday Thursday Friday Saturday Sunday Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec January February March April May June July August September October November December en_PH Mon Tue Wed Thu Fri Sat Sun Monday Tuesday Wednesday Thursday Friday Saturday Sunday Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec January February March April May June July August September October November December en_SG Mon Tue Wed Thu Fri Sat Sun Monday Tuesday Wednesday Thursday Friday Saturday Sunday Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec January February March April May June July August September October November December en_US Mon Tue Wed Thu Fri Sat Sun Monday Tuesday Wednesday Thursday Friday Saturday Sunday Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec January February March April May June July August September October November December en_ZA Mon Tue Wed Thu Fri Sat Sun Monday Tuesday Wednesday Thursday Friday Saturday Sunday Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec January February March April May June July August September October November December en_ZM Mon Tue Wed Thu Fri Sat Sun Monday Tuesday Wednesday Thursday Friday Saturday Sunday Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec January February March April May June July August September October November December en_ZW Mon Tue Wed Thu Fri Sat Sun Monday Tuesday Wednesday Thursday Friday Saturday Sunday Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec January February March April May June July August September October November December es_AR lun mar mié jue vie sáb dom lunes martes miércoles jueves viernes sábado domingo ene feb mar abr may jun jul ago sep oct nov dic enero febrero marzo abril mayo junio julio agosto septiembre octubre noviembre diciembre es_BO lun mar mié jue vie sáb dom lunes martes miércoles jueves viernes sábado domingo ene feb mar abr may jun jul ago sep oct nov dic enero febrero marzo abril mayo junio julio agosto septiembre octubre noviembre diciembre es_CL lun mar mié jue vie sáb dom lunes martes miércoles jueves viernes sábado domingo ene feb mar abr may jun jul ago sep oct nov dic enero febrero marzo abril mayo junio julio agosto septiembre octubre noviembre diciembre es_CO lun mar mié jue vie sáb dom lunes martes miércoles jueves viernes sábado domingo ene feb mar abr may jun jul ago sep oct nov dic enero febrero marzo abril mayo junio julio agosto septiembre octubre noviembre diciembre es_CR lun mar mié jue vie sáb dom lunes martes miércoles jueves viernes sábado domingo ene feb mar abr may jun jul ago sep oct nov dic enero febrero marzo abril mayo junio julio agosto septiembre octubre noviembre diciembre es_CU lun mar mié jue vie sáb dom lunes martes miércoles jueves viernes sábado domingo ene feb mar abr may jun jul ago sep oct nov dic enero febrero marzo abril mayo junio julio agosto septiembre octubre noviembre diciembre es_DO lun mar mié jue vie sáb dom lunes martes miércoles jueves viernes sábado domingo ene feb mar abr may jun jul ago sep oct nov dic enero febrero marzo abril mayo junio julio agosto septiembre octubre noviembre diciembre es_EC lun mar mié jue vie sáb dom lunes martes miércoles jueves viernes sábado domingo ene feb mar abr may jun jul ago sep oct nov dic enero febrero marzo abril mayo junio julio agosto septiembre octubre noviembre diciembre es_ES lun mar mié jue vie sáb dom lunes martes miércoles jueves viernes sábado domingo ene feb mar abr may jun jul ago sep oct nov dic enero febrero marzo abril mayo junio julio agosto septiembre octubre noviembre diciembre es_GT lun mar mié jue vie sáb dom lunes martes miércoles jueves viernes sábado domingo ene feb mar abr may jun jul ago sep oct nov dic enero febrero marzo abril mayo junio julio agosto septiembre octubre noviembre diciembre es_HN lun mar mié jue vie sáb dom lunes martes miércoles jueves viernes sábado domingo ene feb mar abr may jun jul ago sep oct nov dic enero febrero marzo abril mayo junio julio agosto septiembre octubre noviembre diciembre es_MX lun mar mié jue vie sáb dom lunes martes miércoles jueves viernes sábado domingo ene feb mar abr may jun jul ago sep oct nov dic enero febrero marzo abril mayo junio julio agosto septiembre octubre noviembre diciembre es_NI lun mar mié jue vie sáb dom lunes martes miércoles jueves viernes sábado domingo ene feb mar abr may jun jul ago sep oct nov dic enero febrero marzo abril mayo junio julio agosto septiembre octubre noviembre diciembre es_PA lun mar mié jue vie sáb dom lunes martes miércoles jueves viernes sábado domingo ene feb mar abr may jun jul ago sep oct nov dic enero febrero marzo abril mayo junio julio agosto septiembre octubre noviembre diciembre es_PE lun mar mié jue vie sáb dom lunes martes miércoles jueves viernes sábado domingo ene feb mar abr may jun jul ago sep oct nov dic enero febrero marzo abril mayo junio julio agosto septiembre octubre noviembre diciembre es_PR lun mar mié jue vie sáb dom lunes martes miércoles jueves viernes sábado domingo ene feb mar abr may jun jul ago sep oct nov dic enero febrero marzo abril mayo junio julio agosto septiembre octubre noviembre diciembre es_PY lun mar mié jue vie sáb dom lunes martes miércoles jueves viernes sábado domingo ene feb mar abr may jun jul ago sep oct nov dic enero febrero marzo abril mayo junio julio agosto septiembre octubre noviembre diciembre es_SV lun mar mié jue vie sáb dom lunes martes miércoles jueves viernes sábado domingo ene feb mar abr may jun jul ago sep oct nov dic enero febrero marzo abril mayo junio julio agosto septiembre octubre noviembre diciembre es_US lun mar mié jue vie sáb dom lunes martes miércoles jueves viernes sábado domingo ene feb mar abr may jun jul ago sep oct nov dic enero febrero marzo abril mayo junio julio agosto septiembre octubre noviembre diciembre es_UY lun mar mié jue vie sáb dom lunes martes miércoles jueves viernes sábado domingo ene feb mar abr may jun jul ago sep oct nov dic enero febrero marzo abril mayo junio julio agosto septiembre octubre noviembre diciembre es_VE lun mar mié jue vie sáb dom lunes martes miércoles jueves viernes sábado domingo ene feb mar abr may jun jul ago sep oct nov dic enero febrero marzo abril mayo junio julio agosto septiembre octubre noviembre diciembre et_EE E T K N R L P esmaspäev teisipäev kolmapäev neljapäev reede laupäev pühapäev jaan veebr märts apr mai juuni juuli aug sept okt nov dets jaanuar veebruar märts aprill mai juuni juuli august september oktoober november detsember eu_ES al. ar. az. og. or. lr. ig. astelehena asteartea asteazkena osteguna ostirala larunbata igandea urt ots mar api mai eka uzt abu ira urr aza abe urtarrila otsaila martxoa apirila maiatza ekaina uztaila abuztua iraila urria azaroa abendua fa_IR دوشنبه سه‌شنبه چهارشنبه پنجشنبه جمعه شنبه یکشنبه دوشنبه سه‌شنبه چهارشنبه پنجشنبه جمعه شنبه یکشنبه ژانویه فوریه مارس آوریل مه ژوئن ژوئیه اوت سپتامبر اكتبر نوامبر دسامبر ژانویه فوریه مارس آوریل مه ژوئن ژوئیه اوت سپتامبر اكتبر نوامبر دسامبر ff_SN aaɓ maw nje naa mwd hbi dew aaɓnde mawbaare njeslaare naasaande mawnde hoore-biir dewo sii col mbo see duu kor mor juk slt yar jol bow siilo colte mbooy seeɗto duujal korse morso juko siilto yarkomaa jolal bowte fi_FI ma ti ke to pe la su maanantai tiistai keskiviikko torstai perjantai lauantai sunnuntai tammi helmi maalis huhti touko kesä heinä elo syys loka marras joulu tammikuu helmikuu maaliskuu huhtikuu toukokuu kesäkuu heinäkuu elokuu syyskuu lokakuu marraskuu joulukuu fil_PH Lun Mar Miy Huw Biy Sab Lin Lunes Martes Miyerkoles Huwebes Biyernes Sabado Linggo Ene Peb Mar Abr May Hun Hul Ago Sep Okt Nob Dis Enero Pebrero Marso Abril Mayo Hunyo Hulyo Agosto Septiyembre Oktubre Nobiyembre Disyembre fo_FO mán týs mik hós frí ley sun mánadagur týsdagur mikudagur hósdagur fríggjadagur leygardagur sunnudagur jan feb mar apr mai jun jul aug sep okt nov des januar februar mars apríl mai juni juli august september oktober november desember fr_BE lun mar mer jeu ven sam dim lundi mardi mercredi jeudi vendredi samedi dimanche jan fév mar avr mai jun jui aoû sep oct nov déc janvier février mars avril mai juin juillet août septembre octobre novembre décembre fr_CA lun mar mer jeu ven sam dim lundi mardi mercredi jeudi vendredi samedi dimanche jan fév mar avr mai jun jui aoû sep oct nov déc janvier février mars avril mai juin juillet août septembre octobre novembre décembre fr_CH lun mar mer jeu ven sam dim lundi mardi mercredi jeudi vendredi samedi dimanche jan fév mar avr mai jun jui aoû sep oct nov déc janvier février mars avril mai juin juillet août septembre octobre novembre décembre fr_FR lun. mar. mer. jeu. ven. sam. dim. lundi mardi mercredi jeudi vendredi samedi dimanche janv. févr. mars avril mai juin juil. août sept. oct. nov. déc. janvier février mars avril mai juin juillet août septembre octobre novembre décembre fr_LU lun mar mer jeu ven sam dim lundi mardi mercredi jeudi vendredi samedi dimanche jan fév mar avr mai jun jui aoû sep oct nov déc janvier février mars avril mai juin juillet août septembre octobre novembre décembre fur_IT Lun Mar Mia Joi Vin Sab Dom Lunis Martars Miarcus Joibe Vinars Sabide Domenie Zen Fev Mar Avr Mai Jug Lui Avo Set Otu Nov Dec Zenâr Fevrâr Març Avrîl Mai Jugn Lui Avost Setembar Otubar Novembar Decembar fy_DE Mdg Dsg Mwk Ddg Fdg Swd Sdg Mondag Dingsdag Meddwäakj Donnadag Friedag Sinnowend Sinndag Jan Feb Moz Apr Mai Jun Jul Aug Sep Okt Now Dez Jaunuwoa Februwoa Moaz Aprell Mai Juni Juli August Septamba Oktoba Nowamba Dezamba fy_NL Mo Ti Wo To Fr Sn Sn Moandei Tiisdei Woansdei Tongersdei Freed Sneon Snein Jan Feb Maa Apr Maa Jun Jul Aug Sep Okt Nov Des Janaris Febrewaris Maart April Maaie Juny July Augustus Septimber Oktober Novimber Desimber ga_IE Luan Máirt Céad Déar Aoine Sath Domh Dé Luain Dé Máirt Dé Céadaoin Déardaoin Dé hAoine Dé Sathairn Dé Domhnaigh Ean Feabh Márta Aib Beal Meith Iúil Lún MFómh DFómh Samh Noll Eanáir Feabhra Márta Aibreán Bealtaine Meitheamh Iúil Lúnasa Meán Fómhair Deireadh Fómhair Samhain Nollaig gd_GB Dilu Dim Dic Diar Diha Disa Dido Diluain Dimàirt Diciadain Diardaoin Dihaoine Disathairne Didòmhnaich Fao Gea Màr Gib Mhà OgM luc Lùn Sul Dam Sam Dùb Am Faoilteach An Gearran Am Màrt An Giblean A' Mhàigh An t-Mhìos An t-luchar An Lùnasdal An t-Sultain An Damhair An t-Samhain An Dùbhlachd gez_ER ሰኑይ ሠሉስ ራብዕ ሐሙስ ዓርበ ቀዳሚ እኁድ ሰኑይ ሠሉስ ራብዕ ሐሙስ ዓርበ ቀዳሚት እኁድ ጠሐረ ከተተ መገበ አኀዘ ግንባ ሠንየ ሐመለ ነሐሰ ከረመ ጠቀመ ኀደረ ኀሠሠ ጠሐረ ከተተ መገበ አኀዘ ግንባት ሠንየ ሐመለ ነሐሰ ከረመ ጠቀመ ኀደረ ኀሠሠ gez_ET ሰኑይ ሠሉስ ራብዕ ሐሙስ ዓርበ ቀዳሚ እኁድ ሰኑይ ሠሉስ ራብዕ ሐሙስ ዓርበ ቀዳሚት እኁድ ጃንዩ ፌብሩ ማርች ኤፕረ ሜይ ጁን ጁላይ ኦገስ ሴፕቴ ኦክተ ኖቬም ዲሴም ጃንዩወሪ ፌብሩወሪ ማርች ኤፕረል ሜይ ጁን ጁላይ ኦገስት ሴፕቴምበር ኦክተውበር ኖቬምበር ዲሴምበር gl_ES Lun Mar Mér Xov Ven Sáb Dom Luns Martes Mércores Xoves Venres Sábado Domingo Xan Feb Mar Abr Mai Xuñ Xul Ago Set Out Nov Dec Xaneiro Febreiro Marzo Abril Maio Xuño Xullo Agosto Setembro Outubro Novembro Decembro gu_IN સોમ મંગળ બુધ ગુરુ શુક્ર શનિ રવિ સોમવાર મંગળવાર બુધવાર ગુરુવાર શુક્રવાર શનિવાર રવિવાર જાન ફેબ માર એપ્ર મે જુન જુલ ઓગ સપ્ટ ઓક્ટ નોવ ડિસ જાન્યુઆરી ફેબ્રુઆરી માર્ચ એપ્રિલ મે જુન જુલાઇ ઓગસ્ટ સપ્ટેમ્બર ઓક્ટોબર નવેમ્બર ડિસેમ્બર gv_GB Jel Jem Jerc Jerd Jeh Jes Jed Jelhein Jemayrt Jercean Jerdein Jeheiney Jesarn Jedoonee J-guer T-arree Mayrnt Avrril Boaldyn M-souree J-souree Luanistyn M-fouyir J-fouyir M.Houney M.Nollick Jerrey-geuree Toshiaght-arree Mayrnt Averil Boaldyn Mean-souree Jerrey-souree Luanistyn Mean-fouyir Jerrey-fouyir Mee Houney Mee ny Nollick ha_NG Lit Tal Lar Alh Jum Asa Lah Litini Talata Laraba Alhamis Juma'a Asabar Lahadi Jan Fab Mar Afr May Yun Yul Agu Sat Okt Nuw Dis Janairu Fabrairu Maris Afrilu Mayu Yuni Yuli Agusta Satumba Oktoba Nuwamba Disamba hak_TW Mon Tue Wed Thu Fri Sat Sun Monday Tuesday Wednesday Thursday Friday Saturday Sunday Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec January February March April May June July August September October November December he_IL ב' ג' ד' ה' ו' ש' א' שני שלישי רביעי חמישי שישי שבת ראשון ינו פבר מרץ אפר מאי יונ יול אוג ספט אוק נוב דצמ ינואר פברואר מרץ אפריל מאי יוני יולי אוגוסט ספטמבר אוקטובר נובמבר דצמבר hi_IN सोम मंगल बुध गुरु शुक्र शनि रवि सोमवार मंगलवार बुधवार गुरुवार शुक्रवार शनिवार रविवार जनवरी फ़रवरी मार्च अप्रेल मई जून जुलाई अगस्त सितम्बर अक्टूबर नवम्बर दिसम्बर जनवरी फ़रवरी मार्च अप्रेल मई जून जुलाई अगस्त सितम्बर अक्टूबर नवम्बर दिसम्बर hne_IN सोम मंग बुध बिर सुक सनि इत सोमवार मंगलवार बुधवार बिरसपत सुकरवार सनिवार इतवार जन फर मार्च अप मई जून जुला अग सित अकटू नव दिस जनवरी फरवरी मार्च अपरेल मई जून जुलाई अगस्त सितमबर अकटूबर नवमबर दिसमबर hr_HR Pon Uto Sri Čet Pet Sub Ned Ponedjeljak Utorak Srijeda Četvrtak Petak Subota Nedjelja Sij Vel Ožu Tra Svi Lip Srp Kol Ruj Lis Stu Pro Siječanj Veljača Ožujak Travanj Svibanj Lipanj Srpanj Kolovoz Rujan Listopad Studeni Prosinac hsb_DE Pó Wu Sr Št Pj So Nj Póndźela Wutora Srjeda Štvórtk Pjatk Sobota Njedźela Jan Feb Měr Apr Mej Jun Jul Awg Sep Okt Now Dec Januar Februar Měrc Apryl Meja Junij Julij Awgust September Oktober Nowember December ht_HT lEn. mad. mèk. jEd. van. sam. dim. lEndi madi mèkREdi jEdi vandREdi samdi dimanch janv. fEvR. mas avRil mE jEn jiyè. oUt sEpt. okt. nov. dEs. janvyE fEvRiyE mas avRil mE jEn jiyè oUt sEptanm octobRE novanm dEsanm hu_HU h k sze cs p szo v hétfő kedd szerda csütörtök péntek szombat vasárnap jan febr márc ápr máj jún júl aug szept okt nov dec január február március április május június július augusztus szeptember október november december hy_AM Երկ Երք Չրք Հնգ Ուր Շբթ Կրկ Երկուշաբթի Երեքշաբթի Չորեքշաբթի Հինգշաբթի Ուրբաթ Շաբաթ Կիրակի Հնվ Փտր Մար Ապր Մայ Հնս Հլս Օգս Սեպ Հոկ Նմբ Դեկ Հունվարի Փետրվարի Մարտի Ապրիլի Մայիսի Հունիսի Հուլիսի Օգոստոսի Սեպտեմբերի Հոկտեմբերի Նոյեմբերի Դեկտեմբերի ia_FR lun mar mer jov ven sab dom lunedi martedi mercuridi jovedi venerdi sabbato dominica jan feb mar apr mai jun jul aug sep oct nov dec januario februario martio april maio junio julio augusto septembre octobre novembre decembre id_ID Sen Sel Rab Kam Jum Sab Min Senin Selasa Rabu Kamis Jumat Sabtu Minggu Jan Peb Mar Apr Mei Jun Jul Agu Sep Okt Nov Des Januari Pebruari Maret April Mei Juni Juli Agustus September Oktober November Desember ig_NG mọn tuz wen tọs fra sat sọn mọnde tuzde wenzde tọsde fraịde satọde sọnde jen feb maa epr mee juu jul ọgọ sep ọkt nọv dis jenụwarị febụrụwarị maachị epreel mee juun julaị ọgọstụ septemba ọktoba nọvemba disemba ik_CA Sav Ila Qit Sis Tal Maq Min Savałłiq Ilaqtchiioiq Qitchiioiq Sisamiioiq Tallimmiioiq Maqinġuoiq Minġuiqsioiq Sñt Sñs Pan Qil Sup Iġñ Itc Tiñ Ami Sik Nip Siq Siqiññaatchiaq Siqiññaasrugruk Paniqsiqsiivik Qilġich Tatqiat Suppivik Iġñivik Itchavik Tiññivik Amiġaiqsivik Sikkuvik Nippivik Siqiñġiḷaq is_IS mán þri mið fim fös lau sun mánudagur þriðjudagur miðvikudagur fimmtudagur föstudagur laugardagur sunnudagur jan feb mar apr maí jún júl ágú sep okt nóv des janúar febrúar mars apríl maí júní júlí ágúst september október nóvember desember it_CH lun mar mer gio ven sab dom lunedì martedì mercoledì giovedì venerdì sabato domenica gen feb mar apr mag giu lug ago set ott nov dic gennaio febbraio marzo aprile maggio giugno luglio agosto settembre ottobre novembre dicembre it_IT lun mar mer gio ven sab dom lunedì martedì mercoledì giovedì venerdì sabato domenica gen feb mar apr mag giu lug ago set ott nov dic gennaio febbraio marzo aprile maggio giugno luglio agosto settembre ottobre novembre dicembre iu_CA ᓇ ᓕ ᐱ ᕿ ᐅ ᓯ ᓈ ᓇᒡᒐᔾᔭᐅ ᓇᒡᒐᔾᔭᐅᓕᖅᑭᑦ ᐱᖓᓲᓕᖅᓯᐅᑦ ᕿᑎᖅᑰᑦ ᐅᓪᓗᕈᓘᑐᐃᓇᖅ ᓯᕙᑖᕕᒃ ᓈᑦᑎᖑᔭᕐᕕᒃ ᔮᓄ ᕕᕗ ᒪᔅ ᐃᐳ ᒪᐃ ᔪᓂ ᔪᓚ ᐊᒋ ᓯᑎ ᐊᑦ ᓄᕕ ᑎᓯ ᔮᓄᐊᓕ ᕕᕗᐊᓕ ᒪᔅᓯ ᐃᐳᓗ ᒪᐃ ᔪᓂ ᔪᓚᐃ ᐊᒋᓯ ᓯᑎᕙ ᐊᑦᑐᕙ ᓄᕕᕙ ᑎᓯᕝᕙ iw_IL ב' ג' ד' ה' ו' ש' א' שני שלישי רביעי חמישי שישי שבת ראשון ינו פבר מרץ אפר מאי יונ יול אוג ספט אוק נוב דצמ ינואר פברואר מרץ אפריל מאי יוני יולי אוגוסט ספטמבר אוקטובר נובמבר דצמבר ja_JP 月 火 水 木 金 土 日 月曜日 火曜日 水曜日 木曜日 金曜日 土曜日 日曜日 1月 2月 3月 4月 5月 6月 7月 8月 9月 10月 11月 12月 1月 2月 3月 4月 5月 6月 7月 8月 9月 10月 11月 12月 ka_GE ორშ სამ ოთხ ხუთ პარ შაბ კვი ორშაბათი სამშაბათი ოთხშაბათი ხუთშაბათი პარასკევი შაბათი კვირა იან თებ მარ აპრ მაი ივნ ივლ აგვ სექ ოქტ ნოე დეკ იანვარი თებერვალი მარტი აპრილი მაისი ივნისი ივლისი აგვისტო სექტემბერი ოქტომბერი ნოემბერი დეკემბერი kk_KZ Дс Сс Ср Бс Жм Сн Жк Дүйсенбі Сейсенбі Сәрсенбі Бейсенбі Жұма Сенбі Жексенбі Қаң Ақп Нау Сәу Мам Мау Шіл Там Қыр Қаз Қар Жел Қаңтар Ақпан Наурыз Сәуір Мамыр Маусым Шілде Тамыз Қыркүйек Қазан Қараша Желтоқсан kl_GL ata mar pin sis tal arf sab ataasinngorneq marlunngorneq pingasunngorneq sisamanngorneq tallimanngorneq arfininngorneq sabaat jan feb mar apr maj jun jul aug sep okt nov dec januari februari martsi aprili maji juni juli augustusi septemberi oktoberi novemberi decemberi km_KH ច អ ពុ ព្រ សុ ស អា ថ្ងៃ​ច័ន្ទ ថ្ងៃ​អង្គារ ថ្ងៃ​ពុធ ថ្ងៃ​ព្រហស្បតិ៍ ថ្ងៃ​សុក្រ ថ្ងៃ​សៅរ៍ ថ្ងៃ​អាទិត្យ ១ ២ ៣ ៤ ៥ ៦ ៧ ៨ ៩ ១០ ១១ ១២ មករា កុម្ភៈ មិនា មេសា ឧសភា មិថុនា កក្កដា សីហា កញ្ញា តុលា វិច្ឆិកា ធ្នូ kn_IN ಸೋ ಮಂ ಬು ಗು ಶು ಶ ರ ಸೋಮವಾರ ಮಂಗಳವಾರ ಬುಧವಾರ ಗುರುವಾರ ಶುಕ್ರವಾರ ಶನಿವಾರ ರವಿವಾರ ಜ ಫೆ ಮಾ ಏ ಮೇ ಜೂ ಜು ಆ ಸೆ ಅ ನ ದ ಜನವರಿ ಫೆಬ್ರವರಿ ಮಾರ್ಚ ಏಪ್ರಿಲ್ ಮೇ ಜೂನ್ ಜುಲಾಯಿ ಆಗಸ್ತು ಸೆಪ್ಟೆಂಬರ ಅಕ್ತೂಬರ ನವೆಂಬರ ದಶಂಬರ ko_KR 월 화 수 목 금 토 일 월요일 화요일 수요일 목요일 금요일 토요일 일요일 1월 2월 3월 4월 5월 6월 7월 8월 9월 10월 11월 12월 1월 2월 3월 4월 5월 6월 7월 8월 9월 10월 11월 12월 kok_IN सोमार मंगळवार बुधवार बेरेसतार शुकरार शेनवार आयतार सोमार मंगळवार बुधवार बेरेसतार शुकरार शेनवार आयतार जेनवरी फेब्ररी मारच एप्रील में जुन जुलै ओगस्ट सेपटेंबर ओकटोबर नोवेंबर दिसेंबर जेनवरी फेब्ररी मारच एप्रील में जुन जुलै ओगस्ट सेपटेंबर ओकटोबर नोवेंबर दिसेंबर ks_IN ژءنتروار بوءںوار بودهوار برىسوار جمع بٹوار آتهوار ژءندروار بوءںوار بودهوار برىسوار جمع بٹوار آتهوار جنوری فروری مارچ اپریل مئ جون جُلئ اگست ستنبر اکتوبر نوںبر دسنبر جنوری فروری مارچ اپریل مئ جون جُلئ اگست ستنبر اکتوبر نوںبر دسنبر ku_TR dus sês çar pên înî sep yêk dusêm sêsêm çarsêm pêncsêm înî sept yêksêm Çil Sib Ada Nîs Gul Hez Tîr Teb Îlo Cot Mij Kan Çile Sibat Adar Nîsan Gulan Hezîran Tîrmeh Tebax Îlon Cotmeh Mijdar Kanûn kw_GB Lun Mth Mhr Yow Gwe Sad Sul De Lun De Merth De Merher De Yow De Gwener De Sadorn De Sul Gen Whe> Mer Ebr Me Evn Gor Est Gwn Hed Du Kev Mys Genver Mys Whevrel Mys Merth Mys Ebrel Mys Me Mys Evan Mys Gortheren Mye Est Mys Gwyngala Mys Hedra Mys Du Mys Kevardhu ky_KG дш ше ша бш жм иш жк дүйшөмбү шейшемби шаршемби бейшемби жума ишемби жекшемби янв фев мар апр май июн июл авг сен окт ноя дек январь февраль март апрель май июнь июль август сентябрь октябрь ноябрь декабрь lb_LU Mé Dë Më Do Fr Sa So Méindeg Dënschdeg Mëttwoch Donneschdeg Freideg Samschdeg Sonndeg Jan Feb Mäe Abr Mee Jun Jul Aug Sep Okt Nov Dez Januar Februar Mäerz Abrëll Mee Juni Juli August September Oktober November Dezember lg_UG Bal Lw2 Lw3 Lw4 Lw5 Lw6 Sab Balaza Lwakubiri Lwakusatu Lwakuna Lwakutaano Lwamukaaga Sabiiti Jan Feb Mar Apu Maa Jun Jul Agu Seb Oki Nov Des Janwaliyo Febwaliyo Marisi Apuli Maayi Juuni Julaai Agusito Sebuttemba Okitobba Novemba Desemba li_BE mao dae goo dón vri z‘o zón maondig daensdig goonsdig dónderdig vriedig zaoterdig zóndig jan fib mie epr mei jun jul aug sep okt nov des jannewarie fibberwarie miert eprèl meij junie julie augustus september oktober november desember li_NL mao dae goo dón vri z‘o zón maondig daensdig goonsdig dónderdig vriedig zaoterdig zóndig jan fib mie epr mei jun jul aug sep okt nov des jannewarie fibberwarie miert eprèl meij junie julie augustus september oktober november desember lij_IT lûn mar mer zêu ven sab dom lûnedì martedì mercUrdì zêggia venardì sabbo domenega zen fev mar arv maz zûg lûg ago set ött nov dix zenâ fevrâ marzo avrî mazzo zûgno lûggio agosto settembre ottobre novembre dixembre lo_LA ຈ. ຄ. ພ. ພຫ. ສ. ສ. ອາ. ຈັນ ອັງຄານ ພຸດ ພະຫັດ ສຸກ ເສົາ ອາທິດ ມ.ກ. ກ.ພ. ມ.ນ. ມ.ສ. ພ.ພ. ມິ.ຖ. ກ.ລ. ສ.ຫ. ກ.ຍ. ຕ.ລ. ພ.ຈ. ທ.ວ. ມັງກອນ ກຸມຟາ ມີນາ ເມສາ ພຶດສະພາ ມິຖຸນາ ກໍລະກົດ ສິງຫາ ກັນຍາ ຕຸລາ ພະຈິກ ທັນວາ lt_LT Pr An Tr Kt Pn Št Sk Pirmadienis Antradienis Trečiadienis Ketvirtadienis Penktadienis Šeštadienis Sekmadienis Sau Vas Kov Bal Geg Bir Lie Rgp Rgs Spa Lap Grd sausio vasario kovo balandžio gegužės birželio liepos rugpjūčio rugsėjo spalio lapkričio gruodžio lv_LV P  O  T  C  Pk S  Sv pirmdiena otrdiena trešdiena ceturtdiena piektdiena sestdiena svētdiena jan feb mar apr mai jūn jūl aug sep okt nov dec janvāris februāris marts aprīlis maijs jūnijs jūlijs augusts septembris oktobris novembris decembris lzh_TW Mon Tue Wed Thu Fri Sat Sun Monday Tuesday Wednesday Thursday Friday Saturday Sunday Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec January February March April May June July August September October November December mag_IN सोमार मंगर बुध बिफे सूक सनिचर एतवार सोमार मंगर बुध बिफे सूक सनिचर एतवार जनवरी फ़रवरी मार्च अप्रेल मई जून जुलाई अगस्त सितम्बर अक्टूबर नवम्बर दिसम्बर जनवरी फ़रवरी मार्च अप्रेल मई जून जुलाई अगस्त सितम्बर अक्टूबर नवम्बर दिसम्बर mai_IN सोम मंगल बुध गुरु शुक्र शनि रवि सोमवार मंगलवार बुधवार गुरुवार शुक्रवार शनिवार रविवार जनवरी फ़रवरी मार्च अप्रेल मई जून जुलाई अगस्त सितम्बर अक्टूबर नवम्बर दिसम्बर जनवरी फ़रवरी मार्च अप्रेल मई जून जुलाई अगस्त सितम्बर अक्टूबर नवम्बर दिसम्बर mg_MG lts tlt lrb lkm zom sab lhd alatsinainy talata alarobia alakamisy zoma sabotsy alahady jan feb mar apr mey jon jol aog sep okt nov des janoary febroary martsa aprily mey jona jolay aogositra septambra oktobra novambra desambra mhr_RU Шчм Кжм Вгч Изр Кгр Шмт Ршр Шочмо Кушкыжмо Вӱргече Изарня Кугарня Шуматкече Рушарня Шрк Пгж Ӱрн Вшр Ага Пдш Срм Срл Идм Шыж Клм Тел Шорыкйол Пургыж Ӱярня Вӱдшор Ага Пеледыш Сӱрем Сорла Идым Шыжа Кылме Теле mi_NZ Ma Tū We Tāi Pa Hā Ta Mane Tūrei Wenerei Tāite Paraire Hātarei Rātapu Kohi Hui Pou Pae Hara Pipi Hōngoi Here Mahu Whi-nu Whi-ra Haki Kohi-tātea Hui-tanguru Poutū-te-rangi Paenga-whāwhā Haratua Pipiri Hōngoingoi Here-turi-kōkā Mahuru Whiringa-ā-nuku Whiringa-ā-rangi Hakihea mk_MK пон вто сре чет пет саб нед понеделник вторник среда четврток петок сабота недела јан фев мар апр мај јун јул авг сеп окт ное дек јануари февруари март април мај јуни јули август септември октомври ноември декември ml_IN തി ചൊ ബു വ്യാ വെ ശ ഞാ തിങ്കള്‍ ചൊവ്വ ബുധന്‍ വ്യാഴം വെള്ളി ശനി ഞായര്‍ ജനു ഫെബ് മാര്‍ ഏപ്ര മെ ജൂണ്‍ ജൂലൈ ആഗ് സെപ് ഒക്ടോ നവം ഡിസം ജനുവരി ഫെബ്രുവരി മാര്‍ച്ച് ഏപ്രില്‍ മെയ് ജൂണ്‍ ജൂലൈ ആഗസ്റ്റ് സെപ്റ്റംബര്‍ ഒക്ടോബര്‍ നവംബര്‍ ഡിസംബര്‍ mn_MN Да Мя Лх Пү Ба Бя Ня Даваа Мягмар Лхагва Пүрэв Баасан Бямба Ням Хул Үхэ Бар Туу Луу Мог Мор Хон Бич Тах Нох Гах Хулгана сарын Үхэр сарын Бар сарын Туулай сарын Луу сарын Могой сарын Морь сарын Хонь сарын Бич сарын Тахиа сарын Нохой сарын Гахай сарын mni_IN নিং লৈবাক য়ুম শগোল ইরা থাং নোং নিংথৌকাবা লৈবাকপোকপা য়ুমশকৈশা শগোলশেন ইরাই থাংজ নোংমাইজিং জান ফেব মার এপ্রি মে জুন জুল আগ সেপ ওক্ত নবে ডিস জানুৱারি ফেব্রুৱারি মার্চ এপ্রিল মে জুন জুলাই আগষ্ট সেপ্তেম্বর ওক্তোবর নবেম্বর ডিসেম্বর mr_IN सोम मंगळ बुध गुरु शुक्र शनि रवि सोमवार मंगळवार बुधवार गुरुवार शुक्रवार शनिवार रविवार जानेवारी फेबृवारी मार्च एप्रिल मे जून जुलै ऑगस्ट सप्टेंबर ऑक्टोबर नोव्हेंबर डिसेंबर जानेवारी फेबृवारी मार्च एप्रिल मे जून जुलै ऑगस्ट सप्टेंबर ऑक्टोबर नोव्हेंबर डिसेंबर ms_MY Isn Sel Rab Kha Jum Sab Ahd Isnin Selasa Rabu Khamis Jumaat Sabtu Ahad Jan Feb Mac Apr Mei Jun Jul Ogos Sep Okt Nov Dis Januari Februari Mac April Mei Jun Julai Ogos September Oktober November Disember mt_MT Tne Tli Erb Ħam Ġim Sib Ħad it-Tnejn it-Tlieta l-Erbgħa il-Ħamis il-Ġimgħa is-Sibt il-Ħadd Jan Fra Mar Apr Mej Ġun Lul Aww Set Ott Nov Diċ Jannar Frar Marzu April Mejju Ġunju Lulju Awwissu Settembru Ottubru Novembru Diċembru my_MM လာ ဂါ ဟူး တေး သော နေ နွေ တနင်္လာ အင်္ဂါ ဗုဒ္ဓဟူး ကြာသပတေး သောကြာ စနေ တနင်္ဂနွေ ဇန် ဖေ မတ် ဧပြီ မေ ဇွန် ဇူ ဩ စက် အောက် နို ဒီ ဇန်နဝါရီ ဖေဖော်ဝါရီ မတ် ဧပြီ မေ ဇွန် ဇူလိုင် ဩဂုတ် စက်တင်ဘာ အောက်တိုဘာ နိုဝင်ဘာ ဒီဇင်ဘာ nan_TW Mon Tue Wed Thu Fri Sat Sun Monday Tuesday Wednesday Thursday Friday Saturday Sunday Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec January February March April May June July August September October November December nb_NO ma. ti. on. to. fr. lø. sø. mandag tirsdag onsdag torsdag fredag lørdag søndag jan. feb. mars april mai juni juli aug. sep. okt. nov. des. januar februar mars april mai juni juli august september oktober november desember nds_DE Maan Ding Migg Dunn Free Svd. Sdag Maandag Dingsdag Middeweek Dunnersdag Freedag Sünnavend Sünndag Jan Feb Mär Apr Mai Jun Jul Aug Sep Okt Nov Dez Jannuaar Feberwaar März April Mai Juni Juli August September Oktober November Dezember nds_NL Mdg Dsg Mwk Ddg Fdg Swd Sdg Mondag Dingsdag Meddwäakj Donnadag Friedag Sinnowend Sinndag Jan Feb Moz Apr Mai Jun Jul Aug Sep Okt Now Dez Jaunuwoa Februwoa Moaz Aprell Mai Juni Juli August Septamba Oktoba Nowamba Dezamba ne_NP सोम मंगल बुध बिहि शुक्र शनि आइत सोमबार मंगलबार बुधबार बिहिबार शुक्रबार शनिबार आइतबार जनवरी फ़रवरी मार्च अप्रेल मई जून जुलाई अगस्त सितम्बर अक्टूबर नवम्बर दिसम्बर जनवरी फ़रवरी मार्च अप्रेल मई जून जुलाई अगस्त सितम्बर अक्टूबर नवम्बर दिसम्बर nhn_MX cei ome yei nau mac chi teo ceilhuitl omeilhuitl yeilhuitl nahuilhuitl macuililhuitl chicuaceilhuitl teoilhuitl ene feb mar abr may jun jul ago sep oct nov dic enero febrero marzo abril mayo junio julio agosto septiembre octubre noviembre diciembre niu_NU Gofua Ua Lotu Tuloto Falaile Faiumu Tapu Aho Gofua Aho Ua Aho Lotu Aho Tuloto Aho Falaile Aho Faiumu Aho Tapu Ian Fep Mas Ape Me Iun Iul Aok Sep Oke Nov Tes Ianuali Fepuali Masi Apelila Me Iuni Iulai Aokuso Sepetema Oketopa Novema Tesemo niu_NZ Gofua Ua Lotu Tuloto Falaile Faiumu Tapu Aho Gofua Aho Ua Aho Lotu Aho Tuloto Aho Falaile Aho Faiumu Aho Tapu Ian Fep Mas Ape Me Iun Iul Aok Sep Oke Nov Tes Ianuali Fepuali Masi Apelila Me Iuni Iulai Aokuso Sepetema Oketopa Novema Tesemo nl_AW ma di wo do vr za zo maandag dinsdag woensdag donderdag vrijdag zaterdag zondag jan feb mrt apr mei jun jul aug sep okt nov dec januari februari maart april mei juni juli augustus september oktober november december nl_BE ma di wo do vr za zo maandag dinsdag woensdag donderdag vrijdag zaterdag zondag jan feb mrt apr mei jun jul aug sep okt nov dec januari februari maart april mei juni juli augustus september oktober november december nl_NL ma di wo do vr za zo maandag dinsdag woensdag donderdag vrijdag zaterdag zondag jan feb mrt apr mei jun jul aug sep okt nov dec januari februari maart april mei juni juli augustus september oktober november december nn_NO må. ty. on. to. fr. la. su. måndag tysdag onsdag torsdag fredag laurdag sundag jan. feb. mars april mai juni juli aug. sep. okt. nov. des. januar februar mars april mai juni juli august september oktober november desember nr_ZA Mvu Bil Tha Ne Hla Gqi Son uMvulo uLesibili lesithathu uLesine ngoLesihlanu umGqibelo uSonto Jan Feb Mat Apr Mey Jun Jul Arh Sep Okt Usi Dis Janabari uFeberbari uMatjhi u-Apreli Meyi Juni Julayi Arhostosi Septemba Oktoba Usinyikhaba Disemba nso_ZA Moš Bed Rar Ne Hla Mok Son Mošupologo Labobedi Laboraro Labone Labohlano Mokibelo LaMorena Jan Feb Mat Apr Mei Jun Jul Ago Set Okt Nof Dis Janaware Febereware Matšhe Aprele Mei June Julae Agostose Setemere Oktobere Nofemere Disemere oc_FR lun mar mec jòu ven sab dim diluns dimars dimecres dijóus divendres disabte dimenge gen feb mar abr mai jun jul ago set oct nov dec genièr febrièr març abrial mai junh julhet agost setembre octobre novembre decembre om_ET Wix Qib Rob Kam Jim San Dil Wiixata Qibxata Roobii Kamiisa Jimaata Sanbata Dilbata Ama Gur Bit Elb Cam Wax Ado Hag Ful Onk Sad Mud Amajjii Guraandhala Bitooteessa Elba Caamsa Waxabajjii Adooleessa Hagayya Fuulbana Onkololeessa Sadaasa Muddee om_KE Wix Qib Rob Kam Jim San Dil Wiixata Qibxata Roobii Kamiisa Jimaata Sanbata Dilbata Ama Gur Bit Elb Cam Wax Ado Hag Ful Onk Sad Mud Amajjii Guraandhala Bitooteessa Elba Caamsa Waxabajjii Adooleessa Hagayya Fuulbana Onkololeessa Sadaasa Muddee or_IN ସୋମ ମଙ୍ଗଳ ବୁଧ ଗୁରୁ ଶୁକ୍ର ଶନି ରବି ସୋମବାର ମଙ୍ଗଳବାର ବୁଧବାର ଗୁରୁବାର ଶୁକ୍ରବାର ଶନିବାର ରବିବାର 1 2 3 4 5 6 7 8 9 10 11 12 ଜାନୁଆରୀ ଫେବୃଆରୀ ମାର୍ଚ୍ଚ ଅପ୍ରେଲ ମଇ ଜୁନ ଜୁଲାଇ ଅଗଷ୍ଟ ସେପ୍ଟେମ୍ବର ଅକ୍ଟୋବର ନଭେମ୍ବର ଡିସେମ୍ବର os_RU Крс Дцг Æрт Цпр Мрб Сбт Хцб Къуырисæр Дыццæг Æртыццæг Цыппæрæм Майрæмбон Сабат Хуыцаубон Янв Фев Мар Апр Май Июн Июл Авг Сен Окт Ноя Дек Январь Февраль Мартъи Апрель Май Июнь Июль Август Сентябрь Октябрь Ноябрь Декабрь pa_IN ਸੋਮ ਮੰਗਲ ਬੁੱਧ ਵੀਰ ਸ਼ੁੱਕਰ ਸ਼ਨਿੱਚਰ ਐਤ ਸੋਮਵਾਰ ਮੰਗਲਵਾਰ ਬੁੱਧਵਾਰ ਵੀਰਵਾਰ ਸ਼ੁੱਕਰਵਾਰ ਸ਼ਨਿੱਚਰਵਾਰ ਐਤਵਾਰ ਜਨਵਰੀ ਫ਼ਰਵਰੀ ਮਾਰਚ ਅਪਰੈਲ ਮਈ ਜੂਨ ਜੁਲਾਈ ਅਗਸਤ ਸਤੰਬਰ ਅਕਤੂਬਰ ਨਵੰਬਰ ਦਸੰਬਰ ਜਨਵਰੀ ਫ਼ਰਵਰੀ ਮਾਰਚ ਅਪਰੈਲ ਮਈ ਜੂਨ ਜੁਲਾਈ ਅਗਸਤ ਸਤੰਬਰ ਅਕਤੂਬਰ ਨਵੰਬਰ ਦਸੰਬਰ pa_PK پير منگل بدھ جمعرات جمعه هفته اتوار پير منگل بدھ جمعرات جمعه هفته اتوار جنوري فروري مارچ اپريل مٓی جون جولاي اگست ستمبر اكتوبر نومبر دسمبر جنوري فروري مارچ اپريل مٓی جون جولاي اگست ستمبر اكتوبر نومبر دسمبر pap_AN lu ma we ra bi sa do Djaluna Djamars Djawebs Djarason Djabierne Djasabra Djadomingo Yan Feb Mar Apr Mei Yün Yül Oug Sèp Okt Nov Des Yanüari Febrüari Mart Aprel Mei Yüni Yüli Ougùstùs Sèptèmber Oktober Novèmber Desèmber pap_AW Mon Tue Wed Thu Fri Sat Sun Monday Tuesday Wednesday Thursday Friday Saturday Sunday Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec January February March April May June July August September October November December pap_CW Mon Tue Wed Thu Fri Sat Sun Monday Tuesday Wednesday Thursday Friday Saturday Sunday Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec January February March April May June July August September October November December pl_PL pon wto śro czw pią sob nie poniedziałek wtorek środa czwartek piątek sobota niedziela sty lut mar kwi maj cze lip sie wrz paź lis gru styczeń luty marzec kwiecień maj czerwiec lipiec sierpień wrzesień październik listopad grudzień ps_AF د. س. چ. پ. ج. ش. ی. دوشنبه سه‌شنبه چارشنبه پنجشنبه جمعه شنبه یکشنبه جنو فبر مار اپر مـې جون جول اګس سپت اکت نوم دسم جنوري فبروري مارچ اپریل مې جون جولاي اګست سپتمبر اکتوبر نومبر دسمبر pt_BR Seg Ter Qua Qui Sex Sáb Dom segunda terça quarta quinta sexta sábado domingo Jan Fev Mar Abr Mai Jun Jul Ago Set Out Nov Dez janeiro fevereiro março abril maio junho julho agosto setembro outubro novembro dezembro pt_PT Seg Ter Qua Qui Sex Sáb Dom Segunda Terça Quarta Quinta Sexta Sábado Domingo Jan Fev Mar Abr Mai Jun Jul Ago Set Out Nov Dez Janeiro Fevereiro Março Abril Maio Junho Julho Agosto Setembro Outubro Novembro Dezembro quz_PE Mon Tue Wed Thu Fri Sat Sun Monday Tuesday Wednesday Thursday Friday Saturday Sunday Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec January February March April May June July August September October November December ro_RO Lu Ma Mi Jo Vi Sb Du luni marţi miercuri joi vineri sâmbătă duminică ian feb mar apr mai iun iul aug sep oct nov dec ianuarie februarie martie aprilie mai iunie iulie august septembrie octombrie noiembrie decembrie ru_RU Пн Вт Ср Чт Пт Сб Вс Понедельник Вторник Среда Четверг Пятница Суббота Воскресенье янв фев мар апр май июн июл авг сен окт ноя дек Январь Февраль Март Апрель Май Июнь Июль Август Сентябрь Октябрь Ноябрь Декабрь ru_UA Пнд Вто Срд Чтв Птн Суб Вск Понедельник Вторник Среда Четверг Пятница Суббота Воскресенье Янв Фев Мар Апр Май Июн Июл Авг Сен Окт Ноя Дек Январь Февраль Март Апрель Май Июнь Июль Август Сентябрь Октябрь Ноябрь Декабрь rw_RW Mbe Kab Gtu Kan Gnu Gnd Mwe Kuwa mbere Kuwa kabiri Kuwa gatatu Kuwa kane Kuwa gatanu Kuwa gatandatu Ku cyumweru Mut Gas Wer Mat Gic Kam Nya Kan Nze Ukw Ugu Uku Mutarama Gashyantare Werurwe Mata Gicuransi Kamena Nyakanga Kanama Nzeli Ukwakira Ugushyingo Ukuboza sa_IN सोम: मंगल: बुध: बृहस्पतिः शुक्र शनि: रविः सोमवासर: मंगलवासर: बुधवासर: बृहस्पतिवासरः शुक्रवासर शनिवासर: रविवासर: जनवरी फ़रवरी मार्च अप्रेल मई जून जुलाई अगस्त सितम्बर अक्टूबर नवम्बर दिसम्बर जनवरी फ़रवरी मार्च अप्रेल मई जून जुलाई अगस्त सितम्बर अक्टूबर नवम्बर दिसम्बर sat_IN ओते बाले सागुन सारदी जारुम ञुहुम सिंगे ओतेमाँहाँ बालेमाँहाँ सागुनमाँहाँ सारदीमाँहाँ जारुममाँहाँ ञुहुममाँहाँ सिंगेमाँहाँ जनवरी फरवरी मार्च अप्रेल मई जुन जुलाई अगस्त सितम्बर अखथबर नवम्बर दिसम्बर जनवरी फरवरी मार्च अप्रेल मई जुन जुलाई अगस्त सितम्बर अखथबर नवम्बर दिसम्बर sc_IT Lun Mar Mèr Jòb Cen Sàb Dom Lunis Martis Mèrcuris Jòbia Cenàbara Sàbadu Domìngu Gen Fri Mar Abr May Làm Arj Aus Cab Lad Don Ida Gennarju Friarju Martzu Abrili Mayu Làmpadas Arjolas Austu Cabudanni Ladàmini Donnyasantu Idas sd_IN سومرُ منگلُ ٻُڌرُ وسپت جُمو ڇنڇر آرتوارُ سومرُ منگلُ ٻُڌرُ وسپت جُمو ڇنڇر آرتوارُ جنوري فبروري مارچ اپريل مي جون جولاءِ آگسٽ سيپٽيمبر آڪٽوبر نومبر ڊسمبر جنوري فبروري مارچ اپريل مي جون جولاءِ آگسٽ سيپٽيمبر آڪٽوبر نومبر ڊسمبر se_NO vuos maŋ gask duor bear láv sotn vuossárga maŋŋebarga gaskavahkku duorasdat bearjadat lávvardat sotnabeaivi ođđj guov njuk cuoŋ mies geas suoi borg čakč golg skáb juov ođđajagemánu guovvamánu njukčamánu cuoŋománu miessemánu geassemánu suoidnemánu borgemánu čakčamánu golggotmánu skábmamánu juovlamánu shs_CA Spe Sel Ske Sme Sts Stq Sxe Spetkesq̓t Selesq̓t Skellesq̓t Smesesq̓t Stselkstesq̓t Stqmekstesq̓t Sxetspesq̓t Kwe Tsi Sqe Éwt Ell Tsp Tqw Ct̓é Qel Wél U7l Tet Pellkwet̓min Pelctsipwen̓ten Pellsqépts Peslléwten Pell7ell7é7llqten Pelltspéntsk Pelltqwelq̓wél̓t Pellct̓éxel̓cten Pesqelqlélten Pesllwélsten Pellc7ell7é7llcwten̓ Pelltetétq̓em si_LK ස අ බ බ්‍ර සි සෙ ඉ සඳුදා අඟහරුවාදා බදාදා බ්‍රහස්පතින්දා සිකුරාදා සෙනසුරාදා ඉරිදා ජන පෙබ මාර් අප්‍රි මැයි ජූනි ජූලි අගෝ සැප් ඔක් නෙවැ දෙසැ ජනවාරි පෙබරවාරි මාර්තු අප්‍රියෙල් මැයි ජූනි ජූලි අගෝස්තු සැප්තැම්බර් ඔක්තෝබර් නොවැම්බර් දෙසැම්බර් sid_ET San Mak Row Ham Arb Qid Sam Sanyo Maakisanyo Roowe Hamuse Arbe Qidaame Sambata Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec January February March April May June July August September October November December sk_SK Po Ut St Št Pi So Ne Pondelok Utorok Streda Štvrtok Piatok Sobota Nedeľa jan feb mar apr máj jún júl aug sep okt nov dec január február marec apríl máj jún júl august september október november december sl_SI pon tor sre čet pet sob ned ponedeljek torek sreda četrtek petek sobota nedelja jan feb mar apr maj jun jul avg sep okt nov dec januar februar marec april maj junij julij avgust september oktober november december so_DJ isn sal arb kha jim sab axa Isniin Salaaso Arbaco Khamiis Jimco Sabti Axad kob lab sad afr sha lix tod sid sag tob kit lit Bisha Koobaad Bisha Labaad Bisha Saddexaad Bisha Afraad Bisha Shanaad Bisha Lixaad Bisha Todobaad Bisha Sideedaad Bisha Sagaalaad Bisha Tobnaad Bisha Kow iyo Tobnaad Bisha Laba iyo Tobnaad so_ET Isn Sal Arb Kha Jim Sab Axa Isniin Salaaso Arbaco Khamiis Jimco Sabti Axad Kob Lab Sad Afr Sha Lix Tod Sid Sag Tob KIT LIT Bisha Koobaad Bisha Labaad Bisha Saddexaad Bisha Afraad Bisha Shanaad Bisha Lixaad Bisha Todobaad Bisha Sideedaad Bisha Sagaalaad Bisha Tobnaad Bisha Kow iyo Tobnaad Bisha Laba iyo Tobnaad so_KE Isn Sal Arb Kha Jim Sab Axa Isniin Salaaso Arbaco Khamiis Jimco Sabti Axad Kob Lab Sad Afr Sha Lix Tod Sid Sag Tob KIT LIT Bisha Koobaad Bisha Labaad Bisha Saddexaad Bisha Afraad Bisha Shanaad Bisha Lixaad Bisha Todobaad Bisha Sideedaad Bisha Sagaalaad Bisha Tobnaad Bisha Kow iyo Tobnaad Bisha Laba iyo Tobnaad so_SO Isn Sal Arb Kha Jim Sab Axa Isniin Salaaso Arbaco Khamiis Jimco Sabti Axad Kob Lab Sad Afr Sha Lix Tod Sid Sag Tob KIT LIT Bisha Koobaad Bisha Labaad Bisha Saddexaad Bisha Afraad Bisha Shanaad Bisha Lixaad Bisha Todobaad Bisha Sideedaad Bisha Sagaalaad Bisha Tobnaad Bisha Kow iyo Tobnaad Bisha Laba iyo Tobnaad sq_AL Hën Mar Mër Enj Pre Sht Die e hënë e martë e mërkurë e enjte e premte e shtunë e diel Jan Shk Mar Pri Maj Qer Kor Gsh Sht Tet Nën Dhj janar shkurt mars prill maj qershor korrik gusht shtator tetor nëntor dhjetor sq_MK Hën Mar Mër Enj Pre Sht Die e hënë e martë e mërkurë e enjte e premte e shtunë e diel Jan Shk Mar Pri Maj Qer Kor Gsh Sht Tet Nën Dhj janar shkurt mars prill maj qershor korrik gusht shtator tetor nëntor dhjetor sr_ME пон уто сри чет пет суб нед понедељак уторак сриједа четвртак петак субота недјеља јан феб мар апр мај јун јул авг сеп окт нов дец јануар фебруар март април мај јун јул август септембар октобар новембар децембар sr_RS пон уто сре чет пет суб нед понедељак уторак среда четвртак петак субота недеља јан феб мар апр мај јун јул авг сеп окт нов дец јануар фебруар март април мај јун јул август септембар октобар новембар децембар ss_ZA Mso Bil Tsa Ne Hla Mgc Son uMsombuluko Lesibili Lesitsatfu Lesine Lesihlanu uMgcibelo Lisontfo Bhi Van Vul Mab Khk Nhl Kho Ngc Nyo Imp Lwe Ngo Bhimbidvwane iNdlovane iNdlovulenkhulu Mabasa Inkhwenkhweti iNhlaba Kholwane iNgci iNyoni Impala Lweti iNgongoni st_ZA Mma Bed Rar Ne Hla Moq Son Mantaha Labobedi Laboraro Labone Labohlano Moqebelo Sontaha Phe Hla TlH Mme Mot Jan Upu Pha Leo Mph Pud Tsh Pherekgong Hlakola Tlhakubele Mmese Motsheanong Phupjane Phupu Phato Leotse Mphalane Pudungwana Tshitwe sv_FI mån tis ons tor fre lör sön måndag tisdag onsdag torsdag fredag lördag söndag jan feb mar apr maj jun jul aug sep okt nov dec januari februari mars april maj juni juli augusti september oktober november december sv_SE mån tis ons tor fre lör sön måndag tisdag onsdag torsdag fredag lördag söndag jan feb mar apr maj jun jul aug sep okt nov dec januari februari mars april maj juni juli augusti september oktober november december sw_KE J3 J4 J5 Alh Ij J1 J2 Jumatatu Jumanne Jumatano Alhamisi Ijumaa Jumamosi Jumapili Jan Feb Mac Apr Mei Jun Jul Ago Sep Okt Nov Des Januari Februari Machi Aprili Mei Juni Julai Agosti Septemba Oktoba Novemba Desemba sw_TZ J3 J4 J5 Alh Ij J1 J2 Jumatatu Jumanne Jumatano Alhamisi Ijumaa Jumamosi Jumapili Jan Feb Mac Apr Mei Jun Jul Ago Sep Okt Nov Des Januari Februari Machi Aprili Mei Juni Julai Agosti Septemba Oktoba Novemba Desemba szl_PL pyń wtŏ str szt pjō sob niy pyńdziŏek wtŏrek strzŏda sztwortek pjōntek sobŏta niydziela sty lut mer kwj moj czy lip siy wrz paź lis gru styczyń luty merc kwjeciyń moj czyrwjyń lipjyń siyrpjyń wrzesiyń październik listopad grudziyń ta_IN தி செ பு வி வெ ச ஞா திங்கள் செவ்வாய் புதன் வியாழன் வெள்ளி சனி ஞாயிறு ஜன பிப் மார் ஏப் மே ஜூன் ஜூலை ஆக செப் அக் நவ டிச ஜனவரி பிப்ரவரி மார்ச் ஏப்ரல் மே ஜூன் ஜூலை ஆகஸ்ட் செப்டம்பர் அக்டோபர் நவம்பர் டிசம்பர் ta_LK தி செ பு வி வெ ச ஞா திங்கள் செவ்வாய் புதன் வியாழன் வெள்ளி சனி ஞாயிறு ஜன பிப் மார் ஏப் மே ஜூன் ஜூலை ஆக செப் அக் நவ டிச ஜனவரி பிப்ரவரி மார்ச் ஏப்ரல் மே ஜூன் ஜூலை ஆகஸ்ட் செப்டம்பர் அக்டோபர் நவம்பர் டிசம்பர் te_IN సోమ మంగళ బుధ గురు శుక్ర శని ఆది సోమవారం మంగళవారం బుధవారం గురువారం శుక్రవారం శనివారం ఆదివారం జనవరి ఫిబ్రవరి మార్చి ఏప్రిల్ మే జూన్ జూలై ఆగస్టు సెప్టెంబరు అక్టోబరు నవంబరు డిసెంబరు జనవరి ఫిబ్రవరి మార్చి ఏప్రిల్ మే జూన్ జూలై ఆగస్టు సెప్టెంబరు అక్టోబరు నవంబరు డిసెంబరు tg_TJ Пнд Втр Срд Чтв Птн Сбт Вск Понедельник Вторник Среда Четверг Пятница Суббота Воскресенье Янв Фев Мар Апр Май Июн Июл Авг Сен Окт Ноя Дек Января Февраля Марта Апреля Мая Июня Июля Августа Сентября Октября Ноября Декабря th_TH จ. อ. พ. พฤ. ศ. ส. อา. จันทร์ อังคาร พุธ พฤหัสบดี ศุกร์ เสาร์ อาทิตย์ ม.ค. ก.พ. มี.ค. เม.ย. พ.ค. มิ.ย. ก.ค. ส.ค. ก.ย. ต.ค. พ.ย. ธ.ค. มกราคม กุมภาพันธ์ มีนาคม เมษายน พฤษภาคม มิถุนายน กรกฎาคม สิงหาคม กันยายน ตุลาคม พฤศจิกายน ธันวาคม the_NP Mon Tue Wed Thu Fri Sat Sun Monday Tuesday Wednesday Thursday Friday Saturday Sunday Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec January February March April May June July August September October November December ti_ER ሰኑይ ሰሉስ ረቡዕ ሓሙስ ዓርቢ ቀዳም ሰንበ ሰኑይ ሰሉስ ረቡዕ ሓሙስ ዓርቢ ቀዳም ሰንበት ጥሪ ለካቲ መጋቢ ሚያዝ ግንቦ ሰነ ሓምለ ነሓሰ መስከ ጥቅም ሕዳር ታሕሳ ጥሪ ለካቲት መጋቢት ሚያዝያ ግንቦት ሰነ ሓምለ ነሓሰ መስከረም ጥቅምቲ ሕዳር ታሕሳስ ti_ET ሰኑይ ሰሉስ ረቡዕ ሓሙስ ዓርቢ ቀዳም ሰንበ ሰኑይ ሰሉስ ረቡዕ ሓሙስ ዓርቢ ቀዳም ሰንበት ጃንዩ ፌብሩ ማርች ኤፕረ ሜይ ጁን ጁላይ ኦገስ ሴፕቴ ኦክተ ኖቬም ዲሴም ጃንዩወሪ ፌብሩወሪ ማርች ኤፕረል ሜይ ጁን ጁላይ ኦገስት ሴፕቴምበር ኦክተውበር ኖቬምበር ዲሴምበር tig_ER ሰኖ ታላሸ ኣረር ከሚሽ ጅምዓ ሰ/ን ሰ/ዓ ሰኖ ታላሸኖ ኣረርባዓ ከሚሽ ጅምዓት ሰንበት ንኢሽ ሰንበት ዓባይ ጥሪ ለካቲ መጋቢ ሚያዝ ግንቦ ሰነ ሓምለ ነሓሰ መስከ ጥቅም ሕዳር ታሕሳ ጥሪ ለካቲት መጋቢት ሚያዝያ ግንቦት ሰነ ሓምለ ነሓሰ መስከረም ጥቅምቲ ሕዳር ታሕሳስ tk_TM Siş Çar Pen Ann Şen Ýek Duş Sişenbe Çarşenbe Penşenbe Anna Şenbe Ýekşenbe Duşenbe Ýan Few Mar Apr Maý Iýn Iýl Awg Sen Okt Noý Dek Ýanwar Fewral Mart Aprel Maý Iýun Iýul Awgust Sentýabr Oktýabr Noýabr Dekabr tl_PH Lun Mar Miy Huw Biy Sab Lin Lunes Martes Miyerkoles Huwebes Biyernes Sabado Linggo Ene Peb Mar Abr May Hun Hul Ago Sep Okt Nob Dis Enero Pebrero Marso Abril Mayo Hunyo Hulyo Agosto Septiyembre Oktubre Nobiyembre Disyembre tn_ZA Mos Bed Rar Ne Tlh Mat Tsh Mosupologo Labobedi Laboraro Labone Labotlhano Lamatlhatso laTshipi Fer Tlh Mop Mor Mot See Phu Pha Lwe Dip Ngw Sed Ferikgong Tlhakole Mopitlwe Moranang Motsheganong Seetebosigo Phukwi Phatwe Lwetse Diphalane Ngwanatsele Sedimonthole tr_CY Pzt Sal Çrş Prş Cum Cts Paz Pazartesi Salı Çarşamba Perşembe Cuma Cumartesi Pazar Oca Şub Mar Nis May Haz Tem Ağu Eyl Eki Kas Ara Ocak Şubat Mart Nisan Mayıs Haziran Temmuz Ağustos Eylül Ekim Kasım Aralık tr_TR Pzt Sal Çrş Prş Cum Cts Paz Pazartesi Salı Çarşamba Perşembe Cuma Cumartesi Pazar Oca Şub Mar Nis May Haz Tem Ağu Eyl Eki Kas Ara Ocak Şubat Mart Nisan Mayıs Haziran Temmuz Ağustos Eylül Ekim Kasım Aralık ts_ZA Mus Bir Har Ne Tlh Mug Son Musumbhunuku Ravumbirhi Ravunharhu Ravumune Ravuntlhanu Mugqivela Sonto Sun Yan Kul Dzi Mud Kho Maw Mha Ndz Nhl Huk N'w Sunguti Nyenyenyani Nyenyankulu Dzivamisoko Mudyaxihi Khotavuxika Mawuwani Mhawuri Ndzhati Nhlangula Hukuri N'wendzamhala tt_RU Дыш Сиш Чәрш Пәнҗ Җом Шим Якш Дышәмбе Сишәмбе Чәршәәмбе Пәнҗешмбе Җомга Шимбә Якшәмбе Янв Фев Мар Апр Май Июн Июл Авг Сен Окт Ноя Дек Января Февраля Марта Апреля Мая Июня Июля Августа Сентября Октября Ноября Декабря ug_CN د س چ پ ج ش ي دۈشەنبە سەيشەنبە چارشەنبە پەيشەنبە جۈمە شەنبە يەكشەنبە قەھرىتان ھۇت نورۇز ئۈمىد باھار سەپەر چىللە تومۇز مىزان ئوغۇز ئوغلاق كۆنەك قەھرىتان ھۇت نورۇز ئۈمىد باھار سەپەر چىللە تومۇز مىزان ئوغۇز ئوغلاق كۆنەك uk_UA пн вт ср чт пт сб нд понеділок вівторок середа четвер п'ятниця субота неділя січ лют бер кві тра чер лип сер вер жов лис гру січень лютий березень квітень травень червень липень серпень вересень жовтень листопад грудень unm_US man tus lel tas pel sat ken manteke tusteke lelai tasteke pelaiteke sateteke kentuwei eni chk xam kwe tai nip lai win tah puk kun mux enikwsi chkwali xamokhwite kwetayoxe tainipen kichinipen lainipen winaminke kichitahkok puksit wini muxkotae ur_IN پیر منگل بدھ جمعرات جمعہ سنیچر اتوار پیر منگل بدھ جمعرات جمعہ سنیچر اتوار جنوری فروری مارچ اپریل مئی جون جولائی اگست ستمبر اكتوبر نومبر دسمبر جنوری فروری مارچ اپریل مئی جون جولائی اگست ستمبر اكتوبر نومبر دسمبر ur_PK پير منگل بدھ جمعرات جمعه هفته اتوار پير منگل بدھ جمعرات جمعه هفته اتوار جنوري فروري مارچ اپريل مٓی جون جولاي اگست ستمبر اكتوبر نومبر دسمبر جنوري فروري مارچ اپريل مٓی جون جولاي اگست ستمبر اكتوبر نومبر دسمبر uz_UZ Mon Tue Wed Thu Fri Sat Sun Monday Tuesday Wednesday Thursday Friday Saturday Sunday Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec January February March April May June July August September October November December ve_ZA Mus Vhi Rar ṋa Ṱan Mug Swo Musumbuluwo Ḽavhuvhili Ḽavhuraru Ḽavhuṋa Ḽavhuṱanu Mugivhela Swondaha Pha Luh Fam Lam Shu Lwi Lwa Ngu Khu Tsh Ḽar Nye Phando Luhuhi Ṱhafamuhwe Lambamai Shundunthule Fulwi Fulwana Ṱhangule Khubvumedzi Tshimedzi Ḽara Nyendavhusiku vi_VN T2 T3 T4 T5 T6 T7 CN Thứ hai Thứ ba Thứ tư Thứ năm Thứ sáu Thứ bảy Chủ nhật Th01 Th02 Th03 Th04 Th05 Th06 Th07 Th08 Th09 Th10 Th11 Th12 Tháng một Tháng hai Tháng ba Tháng tư Tháng năm Tháng sáu Tháng bảy Tháng tám Tháng chín Tháng mười Tháng mười một Tháng mười hai wa_BE lon mår mie dju vén sem dim londi mårdi mierkidi djudi vénrdi semdi dimegne dja fev mås avr may djn djl awo set oct nôv dec djanvî fevrî måss avri may djun djulete awousse setimbe octôbe nôvimbe decimbe wae_CH Män Zis Mit Fro Fri Sam Sun Mäntag Zischtag Mittwuch Frontag Fritag Samschtag Suntag Jen Hor Mär Abr Mei Brá Hei Öig Her Wím Win Chr Jener Hornig Märze Abrille Meije Bráchet Heiwet Öigschte Herbschtmánet Wímánet Wintermánet Chrischtmánet wal_ET ሳይኖ ማቆሳ አሩዋ ሃሙሳ አርባ ቄራ ወጋ ሳይኖ ማቆሳኛ አሩዋ ሃሙሳ አርባ ቄራ ወጋ ጃንዩ ፌብሩ ማርች ኤፕረ ሜይ ጁን ጁላይ ኦገስ ሴፕቴ ኦክተ ኖቬም ዲሴም ጃንዩወሪ ፌብሩወሪ ማርች ኤፕረል ሜይ ጁን ጁላይ ኦገስት ሴፕቴምበር ኦክተውበር ኖቬምበር ዲሴምበር wo_SN alt tal all alx ajj gaa dib altine talaata allarba alxames ajjuma gaawu dib'eer san fee mar awr me suw sul uut sep okt now des sanwiy'e feebriy'e mars awril me suwen sulet uut septaambar oktoobar nowaambar desaambar xh_ZA Mvu Bin Tha Sin Hla Mgq Caw uMvulo lwesiBini lwesiThathu ulweSine lwesiHlanu uMgqibelo iCawa Mqu Mdu Kwi Tsh Can Sil Kha Thu Msi Dwa Nka Mng eyoMqungu eyoMdumba eyoKwindla uTshazimpuzi uCanzibe eyeSilimela eyeKhala eyeThupa eyoMsintsi eyeDwarha eyeNkanga eyoMnga yi_US מאָנ' דינ' מיט' דאָנ' פֿרײַ' שבת זונ' מאָנטיק דינסטיק מיטװאָך דאָנערשטיק פֿרײַטיק שבת זונטיק יאַנ פֿעב מאַר אַפּר מײַ יונ יול אױג סעפּ אָקט נאָװ דעצ יאַנואַר פֿעברואַר מאַרץ אַפּריל מײַ יוני יולי אױגוסט סעפּטעמבער אָקטאָבער נאָװעמבער דעצעמבער yo_NG MON TUE WED THU FRI SAT SUN Ajé Ìṣẹ́gun Ọjọ́rú Ọjọ́bọ̀ Ẹ̀tì Àbámẹ́ta Àìkú JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC Jánúárì Fẹ́búárì Máàṣì Épírì Méè Júùnù Júláì Ọ́ọ́gọsì Sẹ̀tẹ̀ńbà Ọtóbà Nòfẹ̀ńbà Dìsẹ̀ńbà yue_HK 一 二 三 四 五 六 日 星期一 星期二 星期三 星期四 星期五 星期六 星期日 1月 2月 3月 4月 5月 6月 7月 8月 9月 10月 11月 12月 一月 二月 三月 四月 五月 六月 七月 八月 九月 十月 十一月 十二月 zh_CN 一 二 三 四 五 六 日 星期一 星期二 星期三 星期四 星期五 星期六 星期日 1月 2月 3月 4月 5月 6月 7月 8月 9月 10月 11月 12月 一月 二月 三月 四月 五月 六月 七月 八月 九月 十月 十一月 十二月 zh_HK 一 二 三 四 五 六 日 星期一 星期二 星期三 星期四 星期五 星期六 星期日 1月 2月 3月 4月 5月 6月 7月 8月 9月 10月 11月 12月 一月 二月 三月 四月 五月 六月 七月 八月 九月 十月 十一月 十二月 zh_SG 星期一 星期二 星期三 星期四 星期五 星期六 星期日 星期一 星期二 星期三 星期四 星期五 星期六 星期日 一月 二月 三月 四月 五月 六月 七月 八月 九月 十月 十一月 十二月 一月 二月 三月 四月 五月 六月 七月 八月 九月 十月 十一月 十二月 zh_TW 一 二 三 四 五 六 日 週一 週二 週三 週四 週五 週六 週日 1月 2月 3月 4月 5月 6月 7月 8月 9月 10月 11月 12月 一月 二月 三月 四月 五月 六月 七月 八月 九月 十月 十一月 十二月 zu_ZA Mso Bil Tha Sin Hla Mgq Son uMsombuluko uLwesibili uLwesithathu uLwesine uLwesihlanu uMgqibelo iSonto Mas Ola Nda Mba Aba Ang Ntu Ncw Man Mfu Lwe Zib uMasingana uNhlolanja uNdasa uMbasa uNhlaba uNhlangulana uNtulikazi uNcwaba uMandulo uMfumfu uLwezi uZibandlela dateutils-0.4.5/info/000077500000000000000000000000001335042257000144525ustar00rootroot00000000000000dateutils-0.4.5/info/Makefile.am000066400000000000000000000265601335042257000165170ustar00rootroot00000000000000# Help the Developers and yourself. Just use the C locale and settings # for the compilation. They can still be overriden by make LANG= # but that is general a not very good idea LANG=C LC_ALL=C include $(top_builddir)/version.mk BUILT_SOURCES = EXTRA_DIST = $(BUILT_SOURCES) SUFFIXES = info_TEXINFOS = dateutils.texi dateutils_TEXINFOS = dateutils_TEXINFOS += $(built_texis) dateutils_TEXINFOS += format.texi dateutils_TEXINFOS += format-ddiff.texi dateutils_TEXINFOS += units.texi dateutils_TEXINFOS += zone.texi dateutils_TEXINFOS += locale.texi man1_MANS = man1_MANS += $(built_mans) man1_MANS += dateutils.man dateutils_EXAMPLES = dateutils_H2M_EX = dconv_EXAMPLES = dconv_EXAMPLES += $(top_srcdir)/test/dconv.001.clit dconv_EXAMPLES += $(top_srcdir)/test/dconv.002.clit dconv_EXAMPLES += $(top_srcdir)/test/dconv.003.clit dconv_EXAMPLES += $(top_srcdir)/test/dconv.004.clit dconv_EXAMPLES += $(top_srcdir)/test/tconv.001.clit dconv_EXAMPLES += $(top_srcdir)/test/tconv.002.clit dconv_EXAMPLES += $(top_srcdir)/test/dtconv.001.clit dconv_EXAMPLES += $(top_srcdir)/test/dtconv.002.clit dconv_EXAMPLES += $(top_srcdir)/test/dtconv.011.clit dconv_EXAMPLES += $(top_srcdir)/test/dtconv.012.clit dconv_EXAMPLES += $(top_srcdir)/test/dtconv.014.clit dateutils_EXAMPLES += $(dconv_EXAMPLES) dateutils_H2M_EX += dconv.h2m dseq_EXAMPLES = dseq_EXAMPLES += $(top_srcdir)/test/dseq.01.clit dseq_EXAMPLES += $(top_srcdir)/test/dseq.02.clit dseq_EXAMPLES += $(top_srcdir)/test/dseq.03.clit dseq_EXAMPLES += $(top_srcdir)/test/dseq.04.clit dseq_EXAMPLES += $(top_srcdir)/test/dseq.05.clit dseq_EXAMPLES += $(top_srcdir)/test/dseq.06.clit dseq_EXAMPLES += $(top_srcdir)/test/dseq.07.clit dseq_EXAMPLES += $(top_srcdir)/test/dseq.08.clit dseq_EXAMPLES += $(top_srcdir)/test/dseq.09.clit dseq_EXAMPLES += $(top_srcdir)/test/dseq.10.clit dseq_EXAMPLES += $(top_srcdir)/test/dseq.11.clit dseq_EXAMPLES += $(top_srcdir)/test/dseq.12.clit dseq_EXAMPLES += $(top_srcdir)/test/dseq.13.clit dseq_EXAMPLES += $(top_srcdir)/test/tseq.01.clit dseq_EXAMPLES += $(top_srcdir)/test/tseq.02.clit dseq_EXAMPLES += $(top_srcdir)/test/tseq.03.clit dseq_EXAMPLES += $(top_srcdir)/test/tseq.04.clit dateutils_EXAMPLES += $(dseq_EXAMPLES) dateutils_H2M_EX += dseq.h2m dadd_EXAMPLES = dadd_EXAMPLES += $(top_srcdir)/test/dadd.001.clit dadd_EXAMPLES += $(top_srcdir)/test/dadd.002.clit dadd_EXAMPLES += $(top_srcdir)/test/dadd.003.clit dadd_EXAMPLES += $(top_srcdir)/test/dadd.004.clit dadd_EXAMPLES += $(top_srcdir)/test/tadd.001.clit dadd_EXAMPLES += $(top_srcdir)/test/tadd.002.clit dadd_EXAMPLES += $(top_srcdir)/test/tadd.003.clit dateutils_EXAMPLES += $(dadd_EXAMPLES) dateutils_H2M_EX += dadd.h2m dtest_EXAMPLES = dtest_EXAMPLES += $(top_srcdir)/test/dtest.001.clit dtest_EXAMPLES += $(top_srcdir)/test/dtest.002.clit dtest_EXAMPLES += $(top_srcdir)/test/dtest.003.clit dtest_EXAMPLES += $(top_srcdir)/test/dtest.004.clit dtest_EXAMPLES += $(top_srcdir)/test/dtest.005.clit dtest_EXAMPLES += $(top_srcdir)/test/ttest.001.clit dtest_EXAMPLES += $(top_srcdir)/test/ttest.002.clit dtest_EXAMPLES += $(top_srcdir)/test/ttest.003.clit dtest_EXAMPLES += $(top_srcdir)/test/ttest.004.clit dtest_EXAMPLES += $(top_srcdir)/test/dttest.010.clit dtest_EXAMPLES += $(top_srcdir)/test/dttest.002.clit dtest_EXAMPLES += $(top_srcdir)/test/dttest.003.clit dtest_EXAMPLES += $(top_srcdir)/test/dttest.004.clit dtest_EXAMPLES += $(top_srcdir)/test/dttest.005.clit dateutils_EXAMPLES += $(dtest_EXAMPLES) dateutils_H2M_EX += dtest.h2m ddiff_EXAMPLES = ddiff_EXAMPLES += $(top_srcdir)/test/ddiff.001.clit ddiff_EXAMPLES += $(top_srcdir)/test/ddiff.002.clit ddiff_EXAMPLES += $(top_srcdir)/test/ddiff.003.clit ddiff_EXAMPLES += $(top_srcdir)/test/ddiff.004.clit ddiff_EXAMPLES += $(top_srcdir)/test/ddiff.005.clit ddiff_EXAMPLES += $(top_srcdir)/test/ddiff.006.clit ddiff_EXAMPLES += $(top_srcdir)/test/ddiff.008.clit ddiff_EXAMPLES += $(top_srcdir)/test/tdiff.001.clit ddiff_EXAMPLES += $(top_srcdir)/test/tdiff.002.clit ddiff_EXAMPLES += $(top_srcdir)/test/tdiff.003.clit ddiff_EXAMPLES += $(top_srcdir)/test/tdiff.008.clit ddiff_EXAMPLES += $(top_srcdir)/test/tdiff.006.clit ddiff_EXAMPLES += $(top_srcdir)/test/tdiff.007.clit ddiff_EXAMPLES += $(top_srcdir)/test/dtdiff.001.clit ddiff_EXAMPLES += $(top_srcdir)/test/dtdiff.003.clit ddiff_EXAMPLES += $(top_srcdir)/test/dtdiff.011.clit ddiff_EXAMPLES += $(top_srcdir)/test/dtdiff.012.clit dateutils_EXAMPLES += $(ddiff_EXAMPLES) dateutils_H2M_EX += ddiff.h2m dgrep_EXAMPLES = dgrep_EXAMPLES += $(top_srcdir)/test/dgrep.001.clit dgrep_EXAMPLES += $(top_srcdir)/test/dgrep.002.clit dgrep_EXAMPLES += $(top_srcdir)/test/dgrep.006.clit dgrep_EXAMPLES += $(top_srcdir)/test/dgrep.007.clit dgrep_EXAMPLES += $(top_srcdir)/test/dgrep.008.clit dgrep_EXAMPLES += $(top_srcdir)/test/tgrep.001.clit dgrep_EXAMPLES += $(top_srcdir)/test/tgrep.002.clit dgrep_EXAMPLES += $(top_srcdir)/test/dtgrep.001.clit dgrep_EXAMPLES += $(top_srcdir)/test/dtgrep.002.clit dgrep_EXAMPLES += $(top_srcdir)/test/dtgrep.005.clit dgrep_EXAMPLES += $(top_srcdir)/test/dtgrep.006.clit dateutils_EXAMPLES += $(dgrep_EXAMPLES) dateutils_H2M_EX += dgrep.h2m dround_EXAMPLES = dround_EXAMPLES += $(top_srcdir)/test/dround.002.clit dround_EXAMPLES += $(top_srcdir)/test/dround.003.clit dround_EXAMPLES += $(top_srcdir)/test/tround.003.clit dround_EXAMPLES += $(top_srcdir)/test/tround.002.clit dateutils_EXAMPLES += $(dround_EXAMPLES) dateutils_H2M_EX += dround.h2m dzone_EXAMPLES = dzone_EXAMPLES += $(top_srcdir)/test/dzone.001.clit dzone_EXAMPLES += $(top_srcdir)/test/dzone.002.clit dzone_EXAMPLES += $(top_srcdir)/test/dzone.003.clit dzone_EXAMPLES += $(top_srcdir)/test/dzone.004.clit dateutils_EXAMPLES += $(dzone_EXAMPLES) dateutils_H2M_EX += dzone.h2m dsort_EXAMPLES = dsort_EXAMPLES += $(top_srcdir)/test/dsort.001.clit dsort_EXAMPLES += $(top_srcdir)/test/dsort.002.clit dsort_EXAMPLES += $(top_srcdir)/test/dsort.003.clit dsort_EXAMPLES += $(top_srcdir)/test/dsort.004.clit dsort_EXAMPLES += $(top_srcdir)/test/dsort.005.clit dsort_EXAMPLES += $(top_srcdir)/test/dsort.006.clit dateutils_EXAMPLES += $(dsort_EXAMPLES) dateutils_H2M_EX += dsort.h2m if HAVE_STRPTIME strptime_EXAMPLES = strptime_EXAMPLES += $(top_srcdir)/test/strptime.001.clit strptime_EXAMPLES += $(top_srcdir)/test/strptime.002.clit dateutils_EXAMPLES += $(strptime_EXAMPLES) dateutils_H2M_EX += strptime.h2m endif HAVE_STRPTIME EXTRA_DIST += author.h2m BUILT_SOURCES += format.th2m BUILT_SOURCES += format-ddiff.th2m BUILT_SOURCES += units.th2m BUILT_SOURCES += $(dateutils_H2M_EX) BUILT_SOURCES += $(built_texis) BUILT_SOURCES += $(built_mans) dist_noinst_SCRIPTS = gentexi.sh genh2m.sh texi2h2m.sh built_texis = built_texis += strptime.texi BUILT_SOURCES += dadd.texi BUILT_SOURCES += dconv.texi BUILT_SOURCES += ddiff.texi BUILT_SOURCES += dgrep.texi BUILT_SOURCES += dround.texi BUILT_SOURCES += dseq.texi BUILT_SOURCES += dsort.texi BUILT_SOURCES += dtest.texi BUILT_SOURCES += dzone.texi built_texis += dateadd.texi built_texis += dateconv.texi built_texis += datediff.texi built_texis += dategrep.texi built_texis += dateround.texi built_texis += dateseq.texi built_texis += datesort.texi built_texis += datetest.texi built_texis += datezone.texi built_mans = if HAVE_STRPTIME built_mans += strptime.man endif HAVE_STRPTIME if WITH_OLD_NAMES built_mans += dadd.manu built_mans += dconv.man built_mans += ddiff.mand built_mans += dgrep.man built_mans += dround.manu built_mans += dseq.manu built_mans += dsort.man built_mans += dtest.man built_mans += dzone.man else !WITH_OLD_NAMES built_mans += dateadd.manu built_mans += dateconv.man built_mans += datediff.mand built_mans += dategrep.man built_mans += dateround.manu built_mans += dateseq.manu built_mans += datesort.man built_mans += datetest.man built_mans += datezone.man endif !WITH_OLD_NAMES if WITH_OLD_LINKS ## install them as files, not links built_mans += dadd.manu built_mans += dconv.man built_mans += ddiff.mand built_mans += dgrep.man built_mans += dround.manu built_mans += dseq.manu built_mans += dsort.man built_mans += dtest.man built_mans += dzone.man endif WITH_OLD_LINKS EXTRA_DIST += $(man1_MANS) EXTRA_DIST += $(dateutils_TEXINFOS) ## just to aid the suffix rules strptime.man: strptime.h2m dadd.manu: dadd.h2m dconv.man: dconv.h2m ddiff.mand: ddiff.h2m dgrep.man: dgrep.h2m dround.manu: dround.h2m dseq.manu: dseq.h2m dsort.man: dsort.h2m dtest.man: dtest.h2m dzone.man: dzone.h2m ## new file names TRAFO = sed 's/dadd/dateadd/g; s/dconv/dateconv/g; s/ddiff/datediff/g; s/dgrep/dategrep/g; s/dround/dateround/g; s/dseq/dateseq/g; s/dsort/datesort/g; s/dtest/datetest/g; s/dzone/datezone/g' dateadd.manu: dadd.manu $(TRAFO) < dadd.manu > $@ dateconv.man: dconv.man $(TRAFO) < dconv.man > $@ datediff.mand: ddiff.mand $(TRAFO) < ddiff.mand > $@ dategrep.man: dgrep.man $(TRAFO) < dgrep.man > $@ dateround.manu: dround.manu $(TRAFO) < dround.manu > $@ dateseq.manu: dseq.manu $(TRAFO) < dseq.manu > $@ datesort.man: dsort.man $(TRAFO) < dsort.man > $@ datetest.man: dtest.man $(TRAFO) < dtest.man > $@ datezone.man: dzone.man $(TRAFO) < dzone.man > $@ dateadd.texi: dadd.texi $(TRAFO) < dadd.texi > $@ dateconv.texi: dconv.texi $(TRAFO) < dconv.texi > $@ datediff.texi: ddiff.texi $(TRAFO) < ddiff.texi > $@ dategrep.texi: dgrep.texi $(TRAFO) < dgrep.texi > $@ dateround.texi: dround.texi $(TRAFO) < dround.texi > $@ dateseq.texi: dseq.texi $(TRAFO) < dseq.texi > $@ datesort.texi: dsort.texi $(TRAFO) < dsort.texi > $@ datetest.texi: dtest.texi $(TRAFO) < dtest.texi > $@ datezone.texi: dzone.texi $(TRAFO) < dzone.texi > $@ SUFFIXES += .yuck VPATH = $(srcdir):@top_srcdir@/src SUFFIXES += .man .yuck.man: $(AM_V_GEN) PATH="$(top_builddir)/build-aux:$${PATH}" \ yuck$(EXEEXT) genman \ --package "$(PACKAGE_NAME)" \ --info-page \ -i "$(builddir)/format.th2m" \ -i "$(builddir)/$*.h2m" \ -i "$(srcdir)/author.h2m" \ -o $@ --version-file "$(top_builddir)/.version" $< ## generic rule with format-ddiff instead of format SUFFIXES += .mand .yuck.mand: $(AM_V_GEN) PATH="$(top_builddir)/build-aux:$${PATH}" \ yuck$(EXEEXT) genman \ --package "$(PACKAGE_NAME)" \ --info-page \ -i "$(builddir)/format.th2m" \ -i "$(builddir)/format-ddiff.th2m" \ -i "$(builddir)/$*.h2m" \ -i "$(srcdir)/author.h2m" \ -o $@ --version-file "$(top_builddir)/.version" $< ## generic rule for man pages with units section SUFFIXES += .manu .yuck.manu: $(AM_V_GEN) PATH="$(top_builddir)/build-aux:$${PATH}" \ yuck$(EXEEXT) genman \ --package "$(PACKAGE_NAME)" \ --info-page \ -i "$(builddir)/format.th2m" \ -i "$(builddir)/units.th2m" \ -i "$(builddir)/$*.h2m" \ -i "$(srcdir)/author.h2m" \ -o $@ --version-file "$(top_builddir)/.version" $< my_bld_h2m = $(__bld_h2m_$(V)) __bld_h2m_ = $(__bld_h2m_$(AM_DEFAULT_VERBOSITY)) __bld_h2m_0 = @echo " GENH2M " $*; SUFFIXES += .h2m .yuck.h2m: $(dateutils_EXAMPLES) $(my_bld_h2m) ${SHELL} \ $(srcdir)/genh2m.sh $(top_builddir)/src/$* \ $($*_EXAMPLES) > $@ || rm -f -- $@ my_bld_texi = $(__bld_texi_$(V)) __bld_texi_ = $(__bld_texi_$(AM_DEFAULT_VERBOSITY)) __bld_texi_0 = @echo " GENTEXI " $*; SUFFIXES += .texi .yuck.texi: $(dateutils_EXAMPLES) dateutils.texi $(my_bld_texi) ${SHELL} \ $(srcdir)/gentexi.sh $(top_builddir)/src/$* \ $($*_EXAMPLES) > $@ || test "$$?" = "2" || rm -f -- $@ my_bld_th2m = $(__bld_th2m_$(V)) __bld_th2m_ = $(__bld_th2m_$(AM_DEFAULT_VERBOSITY)) __bld_th2m_0 = @echo " GENTH2M " $*; SUFFIXES += .th2m .texi.th2m: $(my_bld_th2m) ${SHELL} \ $(srcdir)/texi2h2m.sh $< > $@ || rm -f -- $@ ## Makefile.am ends here dateutils-0.4.5/info/author.h2m000066400000000000000000000002141335042257000163610ustar00rootroot00000000000000[Author] Written by Sebastian Freundt [Reporting bugs] Report bugs to: https://github.com/hroptatyr/dateutils/issues dateutils-0.4.5/info/dadd.name000066400000000000000000000000561335042257000162110ustar00rootroot00000000000000[NAME] dadd - Add durations to dates or times dateutils-0.4.5/info/dateutils.man000066400000000000000000000023751335042257000171540ustar00rootroot00000000000000.TH DATEUTILS "1" "September 2012" "dateutils" "User Commands" .SH NAME dateutils \- command line date and time utilities .SH DESCRIPTION dateutils are a bunch of tools that revolve around fiddling with dates and times in the command line with a strong focus on use cases that arise when dealing with large amounts of financial data. .PP .SH COMMANDS .PP \fBdadd\fR(1) .RS 4 Add durations to dates or times .RE .PP \fBdconv\fR(1) .RS 4 Convert dates between calendars or time zones .RE .PP \fBddiff\fR(1) .RS 4 Compute durations between dates and times .RE .PP \fBdgrep\fR(1) .RS 4 Find date or time matches in input stream .RE .PP \fBdround\fR(1) .RS 4 Round dates or times to designated values .RE .PP \fBdseq\fR(1) .RS 4 Generate sequences of dates or times .RE .PP \fBdtest\fR(1) .RS 4 Compare dates or times .RE .PP \fBstrptime\fR(1) .RS 4 Command line version of the C function .RE .SH AUTHOR Written by Sebastian Freundt .SH "REPORTING BUGS" Report bugs to: https://github.com/hroptatyr/dateutils/issues .SH "SEE ALSO" The full documentation for .B dateutils is maintained as a Texinfo manual. If the .B info program is properly installed at your site, the command .IP .B info dateutils .PP should give you access to the complete manual. dateutils-0.4.5/info/dateutils.texi000066400000000000000000000354741335042257000173600ustar00rootroot00000000000000\input texinfo @c -*-texinfo-*- @setfilename dateutils.info @comment node-name, next, previous, up @ifinfo @dircategory Miscellaneous @direntry * dateutils: (dateutils). Command line tools to fiddle with dates. @end direntry @dircategory Individual utilities @direntry * dateadd: (dateutils)dateadd. Add durations to dates or times. * dateconv: (dateutils)dateconv. Convert dates between calendars or time zones. * datediff: (dateutils)datediff. Compute durations between dates and times. * dategrep: (dateutils)dategrep. Find date or time matches in input stream. * dateround: (dateutils)dateround. Round dates or times to designated values. * dateseq: (dateutils)dateseq. Sequences of dates or times. * datesort: (dateutils)datesort. Sort chronologically. * datetest: (dateutils)datetest. Compare dates or times. * datezone: (dateutils)datezone. Convert date/times to different timezones in bulk. * strptime: (dateutils)strptime. Command line version of the C function. @end direntry This manual documents the dateutils package. Copyright @copyright{} 2011-2016 Sebastian Freundt. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License". @end ifinfo @c @setchapternewpage odd @settitle dateutils User's Manual @c @titlepage @sp 6 @center @titlefont{dateutils User's Manual} @sp 4 @sp 1 @sp 1 @center September 2011 @sp 5 @center Sebastian Freundt @page @vskip 0pt plus 1filll Copyright @copyright{} 2011-2016 Sebastian Freundt. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License". @end titlepage @page @node Top @top dateutils dateutils are a bunch of tools that revolve around fiddling with dates and times in the command line with a strong focus on use cases that arise when dealing with large amounts of financial data. @menu * Introduction:: Motivation, background, etc. * Calendars:: Calendar concepts and format specs * Format specifiers and units:: How to control input and output * Localised input and output:: Date/times specific to regions * Algorithms:: Some notes on the algorithms used * dateadd:: Add durations to dates or times * dateconv:: Convert dates between calendars or time zones * datediff:: Compute durations between dates and times * dategrep:: Find date or time matches in input stream * dateround:: Round dates or times to designated values * dateseq:: Generate sequences of dates or times * datesort:: Sort the contents of files chronologically * datetest:: Compare dates or times * datezone:: Convert date/times to timezones in bulk * strptime:: Command line version of the C function @end menu @node Introduction @chapter Introduction The dateutils package is an attempt to provide a comprehensive set of command line tools that behave intuitively, support a similar variety of inputs, allow for normalised output and, most importantly, cover nearly all tasks that arise whilst dealing with huge amounts of dates and unusual calendars. In day to day business, the authors have run across a plethora of approaches to tackle seemingly simple problems. When the command line is a necessity most of these involve perl or awk, which suffer from bad maintainability simply because those tools weren't made to process dates and times in particular, and for the same reason those approaches are anything but fast. And conversely, good maintainability and fast processing is often seen in integrated systems, such as R or database solutions but they come at a price: little flexibility. It's very uncommon to import billions of dates into a database just to compare if they are greater than or equal to a given date. Besides, most of the time those billions of dates come from external sources and have to be brought into shape before or whilst importing them into an integrated system. @node Calendars @chapter Calendars All of the dateutils command line apps are built around a library, libdut. The textual representation of dates is converted to an internal one first, then the date operation is performed and the internal representation in the end is converted back to a textual one. While many of the tools that provide date arithmetic or conversions employ a single standard internal representation (mostly days since a reference date, or seconds since the epoch), the date-core library provides a variety of calendars, each suitable for one or more specific tasks. Usually it's the tool's task to find out which calendar is the best for the task at hand, but to use the library directly we give an overview of the supported calendars here along with some of their properties. @section ymd, aka gregorian This is the `ordinary' calendar, holding a year, a month and the day of the month. Years are subdivided into 12 months, months are subdivided into 28 to 31 days. The canonical input and output format is @code{%Y-%m-%d} (ISO 8601). For outputs the format string @code{ymd} can be used as well. @section ymcw This is a calendric system used at some security exchanges, and can be thought of as a mixture of the year-month-day and year-week-day calendars. It holds a year, a month, a weekday and the count of the weekday within the month. So dates like the third Thursday in March 2011 can be expressed trivially in this system. Years are subdivided into months as in the ymd calendar, months consist of at least 4 and up to 5 weeks and weeks are subdivided into weekdays, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday and Sunday. The canonical input and output format is @code{%Y-%m-%c-%w}. The week is enumerated by 01 for Monday, 02 for Tuesday, @dots{}, 07 for Sunday, as mandated by ISO 8601. For outputs the format string @code{ymcw} can be used as well. @section ywd This calendar is ISO's 8601 year-week-day calendar. Every year is divided into 52 weeks. Every week is divided into 7 days, starting with Monday. To make up for ``missing days'' a leap week is introduced every now and again, i.e. years with leap weeks are 53 weeks long and called leap years (note: ISO does not use the term leap year or leap week). The canonical input and output format is @code{%rY-W%V-%u}, so e.g. 2012-W04-02. Note that ywd years don't necessarily correspond to Gregorian/ymd years, hence the @code{r} modifier in the spec (@code{%rY} is used in calendars to select the ``real'' calendar year). The format string @code{ywd} can be used as well. @section daisy This is one of the most common calendric systems, it counts the days since a given reference date (we originally went for daysi, short for days since, but after the 100th spelling mistake, because daisy is so much more natural, we decided to stick with daisy). In the Julian calendar this was the founding of Rome, in many database systems this is the 1st Jan 1, or other convenient dates like the 1st Jan 1970 or 1st Jan 1900. The (internal) dateutils reference day is the 31st Dec 1600, or equivalently the Naught-th of Jan 1601. This may look like an arbitrary date but it has some interesting properties: - it is a Sunday, so weekday computation is easy as it is a mod 7 operation only - the year is 1 mod 4, so the number of leap years between the reference year and any other year Y is simply Y div 4. In earlier versions we used 1917 for the reference year because it's the first year after 1900 that meets the conditions above. But then we relaxed leap year rules to support dates beyond 2100 (2100 isn't a leap year) so for symmetry reasons we should support years before 1917 in a similar fashion. The daisy calendar has no notion of years or months. The daisy calendar as such has no associated input or output format. This is because we reserve the freedom to change the reference date in the future (like we have done in the past). However, daisy is easily converted to and from other similar day counting systems so their input and output format may be used instead. Also noteworthy on a more informative level, dateutils globally assumes the Gregorian date switch to have taken place in October 1582. This is unlike some other well-known tools (Unix cal for instance) which assume the reformation to have occurred in September 1752. @subsection julian, jdn A close sibling to the daisy system described before is the Julian day number, with reference date 01 Jan 4713 BC in the proleptic Julian calendar. The input and output format string is @code{jdn} or @code{julian}, there is no format specifier. @subsection lilian, ldn Another close sibling to the daisy system is the Lilian day number, its reference date is the first day of the Gregorian calendar, 15 Oct 1582. The input and output format string is @code{ldn} or @code{lilian}, there is no format specifier. @subsection matlab, mdn Taking the Lilian day number further (in a proleptic sense) to the beginning of time, the First of January in year 0, you get the Matlab day number. The input and output format string is @code{mdn} or @code{matlab}, there is no format specifier. @section bizda This calendric system is actually a whole tribe of calendars, in its canonical form this tracks the number of business days after last month's ultimo. Where business day means any non-weekend day. Years are divided into 12 months, each of which consists of 20 to 23 business days. The canonical input and output format is @code{%Y-%m-%db}, where @code{b} is a suffix modifier meaning business days since last month's ultimo. Similarly, @code{%Y-%m-%dB} stands for the business days until this month's ultimo. @node Format specifiers and units @chapter Format specifiers and units The tools provided by dateutils would be pretty meaningless if you could not control how input is to be read or results are to be printed. Following the footsteps of proven systems (such as libc) output formatting is controlled through format specifiers (and flags), as covered by the next 2 sections. Nonetheless, some tools (@samp{dadd}, @samp{dseq}) require durations to be input. Their syntax is covered in the final section. @include format.texi @include format-ddiff.texi @include units.texi @node Localised input and output @chapter Localised input and output Input and output may need to be refined even beyond what simple format specifiers can accomplish, for example time zone information might not be present in the input (or must not be present in the output); or using named weekdays (@samp{%a}, @samp{%A}) or months (@samp{%b}, @samp{%B}) depending on region and language. We present dateutils' solution in the next 2 sections. @include zone.texi @include locale.texi @node Algorithms @chapter Algorithms Coming from a financial background, shaving milliseconds off of code is daily core business. And that in turn is why some of the algorithms used in dateutils might look different to what other people do. In this chapter key concepts are briefly introduced. For implementation details see the @file{*-core.c} and @file{*-core.h} files. @section 32-adic year-days Months, in the Gregorian sense, are roughly 30 days long. Some are longer, one is shorter. It comes in handy though that the average month length is close to a 2-power, 32. So we can introduce a 32-adic year as follows: @verbatim year-day traditional 32-adic m/d 0 19 Jan|00 00|19 1 20 Jan|01 00|20 31 50 Jan|31 01|18 32 51 Feb|01 01|19 59 78 Feb|28 02|14 60 79 Mar|01 02|15 90 109 Mar|31 03|13 91 110 Apr|01 03|14 120 139 Apr|30 04|11 121 140 May|01 04|12 151 170 May|31 05|10 181 200 Jun|30 06|08 212 231 Jul|31 07|07 243 262 Aug|31 08|06 273 292 Sep|30 09|04 304 323 Oct|31 10|03 334 353 Nov|30 11|01 365 384 Dec|31 12|00 @end verbatim As can be seen, the year has 19 unexplained days at the beginning, and, more unintuitively, (traditional) months start in one (32-adic) month and end in another. But the ending always coincides with the traditional months. Another nice thing about this year is that all months end on a different day; this is nice because you can deduce the month just by naming its ending (or the beginning respectively, as all months as a consequence also start on a different day). The final nice thing lies in the property, that months that end (or start) on a day <=16, are affected by the leap day introduced in Feb in the traditional Gregorian calendar. By affected we mean, that the months start (and end) one day off in a leap year. So to cut this story short, the 32-adic year makes computations easier that need a lot of mapping between the day in the year and the month+day representation, e.g. weekday computations (the 32-adic year preserves weekdays as 32 and 7 are co-prime), day differences, etc. The algorithm to get the day of the year from a 32-adic month+day is: @verbatim Input: m <- 32-adic month d <- 32-adic day of month Output: yd -> day of year yd <- m * 32 + d - 19 @end verbatim And conversely. The algorithm to get the 32-adic month+day is trivial. To convert between 32-adic month+day and Gregorian month+day: @verbatim Input: m <- 32-adic month d <- 32-adic day of month Output: m -> 32-adic month d -> 32-adic day of month /* day of month of the beginning and end of m */ bom <- get_beg_of_month(m) eom <- get_end_of_month(m) /* get yd as described above */ yd <- get_yd(m, d) if d <= eom d <- yd - (32 * (m - 1) - 19 + bom - 1) else d <- yd - (32 * m - 19 + eom) m <- m + 1 @end verbatim @include dateadd.texi @include dateconv.texi @include datediff.texi @include dategrep.texi @include dateround.texi @include dateseq.texi @include datesort.texi @include datetest.texi @include datezone.texi @include strptime.texi @summarycontents @contents @bye @c Remember to delete these lines before creating the info file. @iftex @bindingoffset = 0.5in @parindent = 0pt @end iftex dateutils-0.4.5/info/dconv.name000066400000000000000000000000751335042257000164270ustar00rootroot00000000000000[NAME] dconv - Convert dates between calendars or time zones dateutils-0.4.5/info/ddiff.name000066400000000000000000000000711335042257000163660ustar00rootroot00000000000000[NAME] ddiff - Compute durations between dates and times dateutils-0.4.5/info/dgrep.name000066400000000000000000000000711335042257000164130ustar00rootroot00000000000000[NAME] dgrep - Find date or time matches in input stream dateutils-0.4.5/info/dround.name000066400000000000000000000000721335042257000166060ustar00rootroot00000000000000[NAME] dround - Round dates or times to designated values dateutils-0.4.5/info/dseq.name000066400000000000000000000000711335042257000162460ustar00rootroot00000000000000[NAME] ddiff - Compute durations between dates and times dateutils-0.4.5/info/dtest.name000066400000000000000000000000461335042257000164370ustar00rootroot00000000000000[NAME] dtest - Compare dates or times dateutils-0.4.5/info/dzone.name000066400000000000000000000000641335042257000164330ustar00rootroot00000000000000[NAME] dzone - Convert date/times between timezones dateutils-0.4.5/info/format-ddiff.texi000066400000000000000000000071651335042257000177200ustar00rootroot00000000000000@section Format specs for durations Unlike time or absolute instants, durations are reference-free, i.e. the reference instant is not part of the duration. As a result durations cannot be named, i.e. there is no naming scheme that applies to all durations and all references unambiguously. Consequently, none of the format specifiers for date/times makes sense for durations in the literal sense. However, to aid intuitive usage we reused format specifiers when they represent integral values and a valid unit for duration, as follows: Date specs: @verbatim %c Equivalent to %w %d Duration in days %F Equivalent to %dd with no resorting to bigger units %m Duration in months %w Duration in weeks %y Equivalent to %Y %Y Duration in years %db Duration in business days %dB Equivalent to %db @end verbatim Time specs: @verbatim %H Duration in hours %I Equivalent to %H %M Duration in minutes %S Duration in seconds %T Equivalent to %Ss without resorting to bigger units %rS Duration in real-life seconds, as in including leap seconds %rT Equivalent to %rSs without resorting to bigger units @end verbatim General specs: @verbatim %n A newline character %t A tab character %% A literal % character @end verbatim Modifiers: @verbatim %r Modifier to turn units into real units %0 Modifier to pad refined values with zeroes %SPC Modifier to pad refined values with spaces b Suffix, treat days as business days @end verbatim @section The refinement rule Durations are somewhat ambiguous when it comes to representing them through format specifiers. Unlike format specifiers in point-in-time representations duration specifiers can have an intra-line relationship. So for instance a duration of 128 seconds might be presented through @samp{%S} as @samp{128} but similarly through @samp{%M:%S} as @samp{02:08} (read two minutes and 8 seconds). There are several approaches to deal with this ambiguity. The ddiff tool will follow, what we call, the refinement rule. That is, regardless of the position of a format specifier, if it is a valid /refinement/ of another specifier in the format string, then it will only show the fractional value, i.e. the value in its natural range with respect to the /refined/ specifier. @verbatim %Y possible refinements: %m, %w, %d %m possible refinements: %w, %d %w possible refinements: %d %d possible refinements: %H, %M, %S %H possible refinements: %M, %S %M possible refinements: %S @end verbatim The refinement alternatives are listed in order of precedence and they are mutually exclusive. I.e. it is not possible to express a duration in months and hours without having a @samp{%d} specifier as well. On the other hand in a chain of refinements inner elements are optional, i.e. you can express a duration in weeks and hours because every day has 24 hours and hence there are 168 hours in a week. In case of negative durations (the minuend is in the future relative to the subtrahend) only the largest unit will carry the minus sign. Using the refinement rule keeps the format string dead simple, there's no need for operators or a full-blown language to distinguish the range ambiguity, which then would have to be escaped because they could also in theory be part of the literal characters of the format string, resulting more often than not in command lines that are hard to craft and even harder to understand later on (e.g. if used in shell scripts). The refinement rule ingeniously covers the 99% case but, unlike other approaches, there's no way to display two unrefined values in the same format string, e.g. @samp{'%w weeks (which is %d days)'}. dateutils-0.4.5/info/format.texi000066400000000000000000000073061335042257000166430ustar00rootroot00000000000000@section Format specs Format specs in dateutils are similar to posix' strftime(). However, due to a broader range of supported calendars dateutils must employ different rules. Date specs: @verbatim %a The abbreviated weekday name %A The full weekday name %_a The weekday name shortened to a single character (MTWRFAS) %b The abbreviated month name %B The full month name %_b The month name shortened to a single character (FGHJKMNQUVXZ) %c The count of the weekday within the month (range 00 to 05) %C The count of the weekday within the year (range 00 to 53) %d The day of the month, 2 digits (range 00 to 31) %D The day of the year, 3 digits (range 000 to 366) %F Equivalent to %Y-%m-%d (ymd's canonical format) %g ISO week date year without the century (range 00 to 99) %G ISO week date year including the century %j Equivalent to %D %m The month in the current calendar (range 00 to 19) %Q The quarter of the year (range Q1 to Q4) %q The number of the quarter (range 01 to 04) %s The number of seconds since the Epoch. %u The weekday as number (range 01 to 07, Sunday being 07) %U The week count, first day of week is Sun (range 00 to 53) %V The ISO week count, first day of week is Mon (range 01 to 53) %w The weekday as number (range 00 to 06, Sunday being 00) %W The week count, first day of week is Mon (range 00 to 53) %y The year without a century (range 00 to 99) %Y The year including the century %_y The year shortened to a single digit %Z The zone offset in hours and minutes (HH:MM) with a preceding sign (+ for offsets east of UTC, - for offsets west of UTC) %Od The day as roman numerals %Om The month as roman numerals %Oy The two digit year as roman numerals %OY The year including the century as roman numerals %rs In time systems whose Epoch is different from the unix Epoch, this selects the number of seconds since then. %rY In calendars with years that don't coincide with the Gregorian years, this selects the calendar's year. %dth The day of the month as an ordinal number, 1st, 2nd, 3rd, etc. %mth The month of the year as an ordinal number, 1st, 2nd, 3rd, etc. %db The business day of the month (since last month's ultimo) %dB Number of business days until this month's ultimo @end verbatim Time specs: @verbatim %H The hour of the day using a 24h clock, 2 digits (range 00 to 23) %I The hour of the day using a 12h clock, 2 digits (range 01 to 12) %M The minute (range 00 to 59) %N The nanoseconds (range 000000000 to 999999999) %p The string AM or PM, noon is PM and midnight is AM. %P Like %p but in lowercase %S The second (range 00 to 60, 60 is for leap seconds) %T Equivalent to %H:%M:%S @end verbatim General specs: @verbatim %n A newline character %t A tab character %% A literal % character @end verbatim Modifiers: @verbatim %O Modifier to turn decimal numbers into Roman numerals %r Modifier to turn units into real units %0 Modifier to turn on zero prefixes %SPC Modifier to turn on space prefixes %- Modifier to turn off prefixes altogether th Suffix, read and print ordinal numbers b Suffix, treat days as business days @end verbatim By design dates before 1601-01-01 are not supported. For conformity here is a list of calendar designators and their corresponding format string: @verbatim ymd %Y-%m-%d ymcw %Y-%m-%c-%w ywd %rY-W%V-%u bizda %Y-%m-%db lilian n/a ldn n/a julian n/a jdn n/a matlab n/a mdn n/a @end verbatim These designators can be used as output format string, moreover, @code{lilian}/@code{ldn} and @code{julian}/@code{jdn} can also be used as input format string. dateutils-0.4.5/info/genh2m.sh000077500000000000000000000005401335042257000161700ustar00rootroot00000000000000#!/bin/sh ## usage gentexi BINARY if test -x "${1}"; then BINARY="${1}" BINNAME=$(basename "${BINARY}") shift else echo "${1} not a binary" >&2 exit 1 fi echo "[EXAMPLES]" if test "${#}" -eq 0; then exit 0 fi for i; do echo sed '/^#!/d; /ends here$/d; /^[ \t]*$/d; s/@/@@/g; s/{/@{/g; s/}/@}/g s/\\/\\\\/g s/^/ /' "${i}" echo done exit 0 dateutils-0.4.5/info/gentexi.sh000077500000000000000000000013701335042257000164550ustar00rootroot00000000000000#!/bin/sh ## usage gentexi BINARY BINARY="${1}" BINNAME=$(basename "${BINARY}") shift if ! test -x "${BINARY}"; then echo "${BINARY} not found, generating dummy" >&2 cat < $@ || rm -f $@ ## version rules version.c: version.c.in $(top_builddir)/.version $(AM_V_GEN) PATH="$(top_builddir)/build-aux:$${PATH}" \ yuck$(EXEEXT) scmver --ignore-noscm --force -o $@ \ --use-reference --reference $(top_builddir)/.version \ $(srcdir)/version.c.in ## yuck rule SUFFIXES += .yuck SUFFIXES += .yucc .yuck.yucc: $(AM_V_GEN) PATH="$(top_builddir)/build-aux:$${PATH}" \ yuck$(EXEEXT) gen -o $@ $< ## gperf rule SUFFIXES += .gperf .gperf.c: $(AM_V_GEN) $(GPERF) -L ANSI-C $< --output-file $@ ## tzmap rules SUFFIXES += .tzminfo SUFFIXES += .tzmap SUFFIXES += .tzmcc TZMAP_URL := https://raw.github.com/hroptatyr/dateutils/tzmaps .tzminfo.tzmap: -$(AM_V_DL) curl -q -gskfLO -D "$*.hdr" "$(TZMAP_URL)/$@" .tzmap.tzmcc: -$(AM_V_GEN) $(builddir)/tzmap cc -e -o $@ $< ## make sure installing the tzmaps isn't fatal either .IGNORE: install-pkgdataDATA ## for dist or distcheck we need libdut.a dist-hook: $(noinst_LIBRARIES) # # Help the developers get nice post-processed source files ## Create preprocessor output (debugging purposes only) .c.i: $(COMPILE) -E -o $@ $< ## Create assembler output (debugging purposes only) .c.s: $(COMPILE) -S -c $(AM_CFLAGS) $< ## Run Clang static analyzer over sources. anal: $(SOURCES) @list='$(SOURCES)'; \ result=0; \ for file in $$list; do \ if echo $$file | grep '\.c$$' >/dev/null 2>&1; then \ echo "Analyzing $$file"; \ $(ANALYZE_COMMAND) $(srcdir)/$$file; \ status=$$?; \ if test $$status != 0; then \ result=1; \ fi; \ fi; \ done; \ set -e; exit $$result dateutils-0.4.5/lib/bizda.c000066400000000000000000000371551335042257000155350ustar00rootroot00000000000000/*** bizda.c -- guts for bizda dates * * Copyright (C) 2010-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of dateutils. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * **/ #include "boops.h" /* set aspect temporarily */ #define ASPECT_BIZDA /* permanent aspect, to be read as have we ever seen aspect_bizda */ #if !defined ASPECT_BIZDA_ #define ASPECT_BIZDA_ #endif /* !ASPECT_BIZDA_ */ #if !defined DEFUN # define DEFUN #endif /* !DEFUN */ #if !defined BIZDA_ASPECT_HELPERS_ #define BIZDA_ASPECT_HELPERS_ #if defined ASPECT_YMD static int __get_d_equiv(dt_dow_t dow, int b) { /* return the number of gregorian days B business days away from now, * where the first day is on a DOW. */ int res = 0; switch (dow) { case DT_MONDAY: case DT_TUESDAY: case DT_WEDNESDAY: case DT_THURSDAY: case DT_FRIDAY: res += GREG_DAYS_P_WEEK * (b / (signed int)DUWW_BDAYS_P_WEEK); b %= (signed int)DUWW_BDAYS_P_WEEK; break; case DT_SATURDAY: res++; case DT_SUNDAY: res++; b--; res += GREG_DAYS_P_WEEK * (b / (signed int)DUWW_BDAYS_P_WEEK); if ((b %= (signed int)DUWW_BDAYS_P_WEEK) < 0) { /* act as if we're on the monday after */ res++; } dow = DT_MONDAY; break; case DT_MIRACLEDAY: default: break; } /* fixup b */ if (b < 0) { res -= GREG_DAYS_P_WEEK; b += DUWW_BDAYS_P_WEEK; } /* b >= 0 && b < 5 */ switch (dow) { case DT_MONDAY: case DT_TUESDAY: case DT_WEDNESDAY: case DT_THURSDAY: case DT_FRIDAY: if ((int)dow + b <= (int)DT_FRIDAY) { res += b; } else { res += b + 2; } break; case DT_MIRACLEDAY: default: res = 0; break; } return res; } #endif /* ASPECT_YMD */ static int __get_b_equiv(dt_dow_t dow, int d) { /* return the number of business days D gregorian days away from now, * where the first day is on a DOW. */ int res = 0; switch (dow) { case DT_MONDAY: case DT_TUESDAY: case DT_WEDNESDAY: case DT_THURSDAY: case DT_FRIDAY: res += DUWW_BDAYS_P_WEEK * (d / (signed int)GREG_DAYS_P_WEEK); d %= (signed int)GREG_DAYS_P_WEEK; break; case DT_SATURDAY: res--; case DT_SUNDAY: res--; d--; res += DUWW_BDAYS_P_WEEK * (d / (signed int)GREG_DAYS_P_WEEK); if ((d %= (signed int)GREG_DAYS_P_WEEK) < 0) { /* act as if we're on the friday before */ res++; } dow = DT_MONDAY; break; case DT_MIRACLEDAY: default: break; } /* invariant dow + d \in [-6,13] */ switch ((int)dow + d) { case -6: case -5: case -4: case -3: case -2: res += d + 2; break; case -1: res += d + 2; break; case 0: res += d + 1; break; case 1: case 2: case 3: case 4: case 5: res += d; break; case 6: res += d - 1; break; case 7: res += d - 2; break; case 8: case 9: case 10: case 11: case 12: res += d - 2; break; case 13: res += d - 2 - 1; default: break; } return res; } DEFUN __attribute__((pure)) dt_bizda_t __bizda_fixup(dt_bizda_t d) { /* given dates like 2013-08-23b this returns 2013-08-22b */ int bdays; if (LIKELY(d.bd <= 20)) { /* every month has 20 business days */ ; } else if (UNLIKELY(d.m == 0 || d.m > GREG_MONTHS_P_YEAR)) { ; } else if (d.bd > (bdays = __get_bdays(d.y, d.m))) { d.bd = bdays; } return d; } static int __get_nwedays(int dur, dt_dow_t wd) { /* get the number of weekend days in a sequence of DUR days ending on WD * The minimum number of weekend days is simply 2 for every 7 days * to get the exact number observe the following: * * The number of remaining weekend days depends on the remaining number * of days and the DOW of the end point. * * here's the matrix, mod7 down, WD right: * S M T W R F A * 0 0 0 0 0 0 0 0 * 1 1 0 0 0 0 0 1 * 2 2 1 0 0 0 0 1 * 3 2 2 1 0 0 0 1 * 4 2 2 2 1 0 0 1 * 5 2 2 2 2 1 0 1 * 6 2 2 2 2 2 1 1 * * That means * (mod7 == 0) -> 0 * (WD == SAT) -> 1 * (mod7 > WD + 1) -> 2 * (mod7 > WD) -> 1 * * and that's all the magic behind the following code * * Note: If the number of weekend days in a sequence of DUR days starting on WD * (or, equivalently, -DUR days ending on WD before the start day) is sought * after, just use -DUR as input. * * Here's the table for the converse: * S M T W R F A * 0 0 0 0 0 0 0 0 * 1 1 0 0 0 0 1 2 * 2 1 0 0 0 1 2 2 * 3 1 0 0 1 2 2 2 * 4 1 0 1 2 2 2 2 * 5 1 1 2 2 2 2 2 * 6 1 2 2 2 2 2 2 * * mod7 == 0 -> 0 * wd == SUN -> 1 * (mod7 + wd >= 7) -> 2 * (mod7 + wd >= 6) -> 1 */ int nss = (dur / (signed)GREG_DAYS_P_WEEK) * 2; int mod = (dur % (signed)GREG_DAYS_P_WEEK); int xwd = (wd % GREG_DAYS_P_WEEK) + 1; /* saturday fix-up */ nss += wd == DT_SATURDAY; nss += mod + 0 > xwd; nss += mod + 1 > xwd; nss -= mod + 7 < xwd; nss -= mod + 6 < xwd; return nss; } static int __get_nbdays(int dur, dt_dow_t wd) { /* get the number of business days in a sequence of DUR days ending on WD * which is simply the number of days minus the number of weekend-days */ if (dur) { return dur - __get_nwedays(dur, wd); } return 0; } DEFUN unsigned int __get_bdays(unsigned int y, unsigned int m) { /* the 28th exists in every month, and it's exactly 20 bdays * away from the first, oh and it's -1 mod 7 * then to get the number of bdays remaining in the month * from the number of days remaining in the month R * we use a multiplication table, downwards the weekday of the * 28th, rightwards the days in excess of the 28th * Miracleday is only there to make the left hand side of the * multiplication 3 bits wide: * * r-> 0 1 2 3 * Sun 0 1 2 3 * Mon 0 1 2 3 * Tue 0 1 2 3 * Wed 0 1 2 2 * Thu 0 1 1 1 * Fri 0 0 0 1 * Sat 0 0 1 2 * Mir 0 0 0 0 */ unsigned int md = __get_mdays(y, m); /* rd should not overflow */ assert((signed int)md - 28 >= 0); unsigned int rd = (unsigned int)(md - 28U); dt_dow_t m01wd; dt_dow_t m28wd; /* wday of the 1st and 28th */ m01wd = __get_m01_wday(y, m); m28wd = (dt_dow_t)(m01wd - 1 ?: DT_SUNDAY); if (LIKELY(rd > 0)) { switch (m28wd) { case DT_SUNDAY: case DT_MONDAY: case DT_TUESDAY: return 20 + rd; case DT_WEDNESDAY: return 20 + rd - (rd == 3); case DT_THURSDAY: return 21; case DT_FRIDAY: return 20 + (rd == 3); case DT_SATURDAY: return 20 + rd - 1; case DT_MIRACLEDAY: default: abort(); } } return 20U; } #endif /* BIZDA_ASPECT_HELPERS_ */ #if defined ASPECT_GETTERS && !defined BIZDA_ASPECT_GETTERS_ #define BIZDA_ASPECT_GETTERS_ static unsigned int __bizda_get_mday(dt_bizda_t that) { dt_dow_t wd01; unsigned int res; /* find first of the month first */ wd01 = __get_m01_wday(that.y, that.m); switch (wd01) { case DT_MONDAY: case DT_TUESDAY: case DT_WEDNESDAY: case DT_THURSDAY: case DT_FRIDAY: res = 1; break; case DT_SATURDAY: wd01 = DT_MONDAY; res = 3; break; case DT_SUNDAY: wd01 = DT_MONDAY; res = 2; break; case DT_MIRACLEDAY: default: res = 0; break; } /* now just add up bdays */ { unsigned int wk; unsigned int nd; unsigned int b = that.bd; unsigned int magic = (b - 1 + wd01 - 1); assert(b + wd01 >= 2); wk = magic / DUWW_BDAYS_P_WEEK; nd = magic % DUWW_BDAYS_P_WEEK; res += wk * GREG_DAYS_P_WEEK + nd - wd01 + 1; } /* fixup mdays */ if (res > __get_mdays(that.y, that.m)) { res = 0; } return res; } static dt_dow_t __bizda_get_wday(dt_bizda_t that) { dt_dow_t wd01; unsigned int b; unsigned int magic; /* find first of the month first */ wd01 = __get_m01_wday(that.y, that.m); b = that.bd; magic = (b - 1 + (wd01 < DT_SUNDAY ? wd01 : 6) - 1); /* now just add up bdays */ return (dt_dow_t)((magic % DUWW_BDAYS_P_WEEK) + DT_MONDAY); } static unsigned int __bizda_get_count(dt_bizda_t that) { /* get N where N is the N-th occurrence of wday in the month of that year */ unsigned int bd = __get_bdays(that.y, that.m); if (UNLIKELY(that.bd + DUWW_BDAYS_P_WEEK > bd)) { return DUWW_BDAYS_P_WEEK; } return (that.bd - 1U) / DUWW_BDAYS_P_WEEK + 1U; } static unsigned int __bizda_get_yday(dt_bizda_t that, dt_bizda_param_t param) { /* return the N-th business day in Y, * the meaning of ultimo will be stretched to Y-ultimo, either last year's * or this year's, other reference points are not yet supported * * we use the following table (days beyond 20 bdays per month (across)): * Mon 3 0 2 1 3 1 2 3 0 3 2 1 * Mon 3 1 1 rest like Tue * Tue 3 0 1 2 3 0 3 2 1 3 1 2 * Tue 3 1 1 rest like Wed * Wed 3 0 1 2 2 1 3 1 2 3 0 3 * Wed 3 0 2 rest like Thu * Thu 2 0 2 2 1 2 3 1 2 2 1 3 * Thu 2 0 3 rest like Fri * Fri 1 0 3 2 1 2 2 2 2 1 2 3 * Fri 1 1 3 rest like Sat * Sat 1 0 3 1 2 2 1 3 2 1 2 2 * Sat 1 1 3 rest like Sun * Sun 2 0 3 0 3 2 1 3 1 2 2 1 * Sun 2 1 2 rest like Mon * */ struct __bdays_by_wday_s { unsigned int jan:2; unsigned int feb:2; unsigned int mar:2; unsigned int apr:2; unsigned int may:2; unsigned int jun:2; unsigned int jul:2; unsigned int aug:2; unsigned int sep:2; unsigned int oct:2; unsigned int nov:2; unsigned int dec:2; unsigned int feb_leap:2; unsigned int mar_leap:2; /* 4 bits left */ unsigned int flags:4; }; static struct __bdays_by_wday_s tbl[8U] = { { /* DT_MIRACLEDAY */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { /* DT_MONDAY */ 3, 0, 2, 1, 3, 1, 2, 3, 0, 3, 2, 1, 1, 1, 0 }, { /* DT_TUESDAY */ 3, 0, 1, 2, 3, 0, 3, 2, 1, 3, 1, 2, 1, 1, 0 }, { /* DT_WEDNESDAY */ 3, 0, 1, 2, 2, 1, 3, 1, 2, 3, 0, 3, 0, 2, 0 }, { /* DT_THURSDAY */ 2, 0, 2, 2, 1, 2, 3, 1, 2, 2, 1, 3, 0, 3, 0 }, { /* DT_FRIDAY */ 1, 0, 3, 2, 1, 2, 2, 2, 2, 1, 2, 3, 1, 3, 0 }, { /* DT_SATURDAY */ 1, 0, 3, 1, 2, 2, 1, 3, 2, 1, 2, 2, 1, 3, 0 }, { /* DT_SUNDAY */ 2, 0, 3, 0, 3, 2, 1, 3, 1, 2, 2, 1, 1, 2, 0 }, }; dt_dow_t j01wd; unsigned int y = that.y; unsigned int m = that.m; unsigned int accum = 0; if (UNLIKELY(param.ref != BIZDA_ULTIMO)) { return 0; } j01wd = __get_jan01_wday(that.y); if (LIKELY(!__leapp(y))) { union { uint32_t u; uint32_t lu:2; struct __bdays_by_wday_s s; } page = { .s = tbl[j01wd], }; for (unsigned int i = 0; i < m - 1; i++) { accum += page.lu; #if BYTE_ORDER == BIG_ENDIAN page.u <<= 2; #elif BYTE_ORDER == LITTLE_ENDIAN page.u >>= 2; #else # warning unknown byte order #endif /* BYTE_ORDER */ } } else if (m > 1) { union { uint32_t u; uint32_t lu:2; struct __bdays_by_wday_s s; } page = { .s = tbl[j01wd], }; accum += page.lu; if (m > 2) { accum += page.s.feb_leap; } if (m > 3) { accum += page.s.mar_leap; } /* load a different page now, shift to the right month */ page.s = tbl[(j01wd < DT_SUNDAY ? j01wd : 0U) + DT_MONDAY]; #if BYTE_ORDER == BIG_ENDIAN page.u <<= 6; #elif BYTE_ORDER == LITTLE_ENDIAN page.u >>= 6; #else # warning unknown byte order #endif /* BYTE_ORDER */ for (unsigned int i = 4; i < m; i++) { accum += page.lu; #if BYTE_ORDER == BIG_ENDIAN page.u <<= 2; #elif BYTE_ORDER == LITTLE_ENDIAN page.u >>= 2; #else # warning unknown byte order #endif /* BYTE_ORDER */ } } return 20 * (m - 1) + accum + that.bd; } #endif /* BIZDA_ASPECT_GETTERS_ */ #if defined ASPECT_CONV && !defined BIZDA_ASPECT_CONV_ #define BIZDA_ASPECT_CONV_ static dt_ymd_t __bizda_to_ymd(dt_bizda_t d) { unsigned int tgtd = __bizda_get_mday(d); #if defined HAVE_ANON_STRUCTS_INIT return (dt_ymd_t){.y = d.y, .m = d.m, .d = tgtd}; #else /* !HAVE_ANON_STRUCTS_INIT */ dt_ymd_t res; res.y = d.y; res.m = d.m; res.d = tgtd; return res; #endif /* HAVE_ANON_STRUCTS_INIT */ } static dt_ywd_t __bizda_to_ywd(dt_bizda_t d, dt_bizda_param_t p) { unsigned int yd = __bizda_get_yday(d, p); return __make_ywd_ybd(d.y, yd); } static dt_ymcw_t __bizda_to_ymcw(dt_bizda_t d, dt_bizda_param_t UNUSED(p)) { unsigned int c = __bizda_get_count(d); dt_dow_t w = __bizda_get_wday(d); #if defined HAVE_ANON_STRUCTS_INIT return (dt_ymcw_t){.y = d.y, .m = d.m, .c = c, .w = w}; #else dt_ymcw_t res; res.y = d.y; res.m = d.m; res.c = c; res.w = w; return res; #endif } static dt_daisy_t __bizda_to_daisy(dt_bizda_t d, dt_bizda_param_t p) { dt_daisy_t res; unsigned int ybd; unsigned int wd; res = __jan00_daisy(d.y); wd = __daisy_get_wday(res); ybd = __bizda_get_yday(d, p); res += __get_d_equiv((dt_dow_t)wd, ybd); return res; } #endif /* ASPECT_CONV */ #if defined ASPECT_ADD && !defined BIZDA_ASPECT_ADD_ #define BIZDA_ASPECT_ADD_ static dt_bizda_t __bizda_fixup_b(unsigned int y, signed int m, signed int b) { dt_bizda_t res = {0}; if (LIKELY(b >= 1 && b <= 20)) { /* all months in our design range have at least 20 bdays */ ; } else if (b < 1) { int bdays; do { if (UNLIKELY(--m < 1)) { --y; m = GREG_MONTHS_P_YEAR; } bdays = __get_bdays(y, m); b += bdays; } while (b < 1); } else { int bdays; while (b > (bdays = __get_bdays(y, m))) { b -= bdays; if (UNLIKELY(++m > (signed int)GREG_MONTHS_P_YEAR)) { ++y; m = 1; } } } res.y = y; res.m = m; res.bd = b; return res; } static dt_bizda_t __bizda_add_b(dt_bizda_t d, int n) { /* add N business days to D */ int tgtb = d.bd + n; return __bizda_fixup_b(d.y, d.m, tgtb); } static dt_bizda_t __bizda_add_d(dt_bizda_t d, int n) { /* add N real days to D */ dt_dow_t wd = __bizda_get_wday(d); int tgtb = d.bd + __get_b_equiv(wd, n); return __bizda_fixup_b(d.y, d.m, tgtb); } static dt_bizda_t __bizda_add_w(dt_bizda_t d, int n) { /* add N weeks to D */ return __bizda_add_d(d, GREG_DAYS_P_WEEK * n); } static dt_bizda_t __bizda_add_m(dt_bizda_t d, int n) { /* add N months to D */ signed int tgtm = d.m + n; while (tgtm > (signed int)GREG_MONTHS_P_YEAR) { tgtm -= GREG_MONTHS_P_YEAR; ++d.y; } while (tgtm < 1) { tgtm += GREG_MONTHS_P_YEAR; --d.y; } /* final assignment */ d.m = tgtm; return d; } static dt_bizda_t __bizda_add_y(dt_bizda_t d, int n) { /* add N years to D */ d.y += n; return d; } #endif /* ASPECT_ADD */ #if defined ASPECT_STRF && !defined BIZDA_ASPECT_STRF_ #define BIZDA_ASPECT_STRF_ DEFUN void __prep_strfd_bizda(struct strpd_s *tgt, dt_bizda_t d, dt_bizda_param_t bp) { tgt->y = d.y; tgt->m = d.m; tgt->b = d.bd; if (LIKELY(bp.ab == BIZDA_AFTER)) { tgt->flags.ab = BIZDA_AFTER; } else { tgt->flags.ab = BIZDA_BEFORE; } tgt->flags.bizda = 1; return; } #endif /* ASPECT_STRF */ #undef ASPECT_BIZDA /* bizda.c ends here */ dateutils-0.4.5/lib/boops.h000066400000000000000000000204501335042257000155610ustar00rootroot00000000000000/*** boops.h -- byte-order operations * * Copyright (C) 2012-2018 Sebastian Freundt * Copyright (C) 2012 Ruediger Meier * * Author: Sebastian Freundt * * This file is part of uterus, dateutils and atem. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***/ #if !defined INCLUDED_boops_h_ #define INCLUDED_boops_h_ #if defined HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #if defined HAVE_SYS_PARAM_H # include #endif /* HAVE_SYS_PARAM_H */ #if defined HAVE_SYS_TYPES_H # include #endif /* HAVE_SYS_TYPES_H */ /* *bsd except for openbsd */ #if defined HAVE_SYS_ENDIAN_H # include #elif defined HAVE_MACHINE_ENDIAN_H # include #elif defined HAVE_ENDIAN_H # include #elif defined HAVE_BYTEORDER_H # include #endif /* SYS/ENDIAN_H || MACHINE/ENDIAN_H || ENDIAN_H || BYTEORDER_H */ /* check for byteswap to do the swapping ourselves if need be */ #if defined HAVE_BYTESWAP_H # include #endif /* BYTESWAP_H */ #if !defined BYTE_ORDER # if defined __BYTE_ORDER # define BYTE_ORDER __BYTE_ORDER # elif defined __BYTE_ORDER__ # define BYTE_ORDER __BYTE_ORDER__ # else # define BYTE_ORDER -1 # endif #endif /* !BYTE_ORDER */ #if !defined LITTLE_ENDIAN # if defined __ORDER_LITTLE_ENDIAN__ # define LITTLE_ENDIAN __ORDER_LITTLE_ENDIAN__ # elif defined __LITTLE_ENDIAN # define LITTLE_ENDIAN __LITTLE_ENDIAN # elif defined __LITTLE_ENDIAN__ # define LITTLE_ENDIAN __LITTLE_ENDIAN__ # else # define LITTLE_ENDIAN 0 # endif #endif /* !LITTLE_ENDIAN */ #if !defined BIG_ENDIAN # if defined __ORDER_BIG_ENDIAN__ # define BIG_ENDIAN __ORDER_BIG_ENDIAN__ # elif defined __BIG_ENDIAN # define BIG_ENDIAN __BIG_ENDIAN # elif defined __BIG_ENDIAN__ # define BIG_ENDIAN __BIG_ENDIAN__ # else # define BIG_ENDIAN 0 # endif #endif /* !BIG_ENDIAN */ #if BYTE_ORDER == LITTLE_ENDIAN /* do nothing */ #elif BYTE_ORDER == BIG_ENDIAN /* still nothing */ #elif LITTLE_ENDIAN && !BIG_ENDIAN # undef BYTE_ORDER # define BYTE_ORDER LITTLE_ENDIAN #elif BIG_ENDIAN && !LITTLE_ENDIAN # undef BYTE_ORDER # define BYTE_ORDER BIG_ENDIAN #endif /* start off with opposite-endianness converters */ #if defined htooe16 /* yay, nothing to do really */ #elif defined __GNUC__ && __GNUC__ == 4 && __GNUC_MINOR__ >= 7 # define htooe16(x) __builtin_bswap16(x) #elif defined __bswap_16 # define htooe16(x) __bswap_16(x) #elif defined __swap16 # define htooe16(x) __swap16(x) #elif BYTE_ORDER == BIG_ENDIAN && defined le16toh # define htooe16(x) le16toh(x) #elif BYTE_ORDER == LITTLE_ENDIAN && defined be16toh # define htooe16(x) be16toh(x) #else /* do it agnostically */ static inline __attribute__((pure, const)) uint16_t htooe16(uint16_t x) { return ((x >> 8U) & 0xffU) | ((x << 8U) & 0xff00U); } #endif /* htooe16 */ #if !defined be16toh # if defined betoh16 # define be16toh betoh16 # elif BYTE_ORDER == BIG_ENDIAN # define be16toh(x) (x) # else /* means we need swapping */ # define be16toh(x) htooe16(x) # endif /* betoh16 */ #endif /* !be16toh */ #if !defined le16toh # if defined letoh16 # define le16toh letoh16 # elif BYTE_ORDER == BIG_ENDIAN # define le16toh(x) htooe16(x) # else /* no swapping needed */ # define le16toh(x) (x) # endif /* letoh16 */ #endif /* !le16toh */ #if !defined htobe16 # if BYTE_ORDER == BIG_ENDIAN # define htobe16(x) (x) # else /* need swabbing */ # define htobe16(x) htooe16(x) # endif #endif /* !htobe16 */ #if !defined htole16 # if BYTE_ORDER == BIG_ENDIAN # define htole16(x) htooe16(x) # else /* no byte swapping needed */ # define htole16(x) (x) # endif #endif /* !htole16 */ /* just to abstract over pure swapping */ #if defined htooe32 /* yay, nothing to do really */ #elif defined __GNUC__ && __GNUC__ == 4 && __GNUC_MINOR__ >= 7 # define htooe32(x) __builtin_bswap32(x) #elif defined __bswap_32 # define htooe32(x) __bswap_32(x) #elif defined __swap32 # define htooe32(x) __swap32(x) #elif BYTE_ORDER == BIG_ENDIAN && defined le32toh # define htooe32(x) le32toh(x) #elif BYTE_ORDER == LITTLE_ENDIAN && defined be32toh # define htooe32(x) be32toh(x) #else /* do it agnostically */ static inline __attribute__((pure, const)) uint32_t htooe32(uint32_t x) { /* swap them word-wise first */ x = ((x >> 16U) & 0xffffU) | ((x << 16U) & 0xffff0000U); /* do the byte swap */ return ((x >> 8U) & 0xff00ffU) | ((x << 8U) & 0xff00ff00U); } #endif /* and even now we may be out of luck */ #if !defined be32toh # if defined betoh32 # define be32toh betoh32 # elif BYTE_ORDER == BIG_ENDIAN # define be32toh(x) (x) # else /* need some swaps */ # define be32toh(x) htooe32(x) # endif #endif /* !be32toh */ #if !defined le32toh # if defined letoh32 # define le32toh letoh32 # elif BYTE_ORDER == BIG_ENDIAN # define le32toh(x) htooe32(x) # else /* no byte swapping here */ # define le32toh(x) (x) # endif /* letoh32 */ #endif /* !le32toh */ #if !defined htobe32 # if BYTE_ORDER == BIG_ENDIAN # define htobe32(x) (x) # else /* yep, swap me about */ # define htobe32(x) htooe32(x) # endif #endif /* !be32toh */ #if !defined htole32 # if BYTE_ORDER == BIG_ENDIAN # define htole32(x) htooe32(x) # else /* nothing to swap */ # define htole32(x) (x) # endif #endif /* !htole32 */ #if defined htooe64 /* yay, nothing to do really */ #elif defined __GNUC__ && __GNUC__ == 4 && __GNUC_MINOR__ >= 7 # define htooe64(x) __builtin_bswap64(x) #elif defined __bswap_64 # define htooe64(x) __bswap_64(x) #elif defined __swap64 # define htooe64(x) __swap64(x) #elif BYTE_ORDER == BIG_ENDIAN && defined le64toh # define htooe64(x) le64toh(x) #elif BYTE_ORDER == LITTLE_ENDIAN && defined be64toh # define htooe64(x) be64toh(x) #else /* do it agnostically */ static inline __attribute__((pure, const)) uint64_t htooe64(uint64_t x) { /* swap them dword-wise first */ x = ((x >> 32U) & 0xffffffffU) | ((x << 32U) & 0xffffffff00000000U); /* word wise swap now */ x = ((x >> 16U) & 0xffff0000ffffU) | ((x << 16U) & 0xffff0000ffff0000U); /* do the byte swap */ return ((x >> 8U) & 0xff00ff00ff00ffU) | ((x << 8U) & 0xff00ff00ff00ff00U); } #endif #if !defined be64toh # if defined betoh64 # define be64toh betoh64 # elif BYTE_ORDER == BIG_ENDIAN # define be64toh(x) (x) # else /* swapping */ # define be64toh(x) htooe64(x) # endif #endif /* !be64toh */ #if !defined le64toh # if defined letoh64 # define le64toh letoh64 # elif BYTE_ORDER == BIG_ENDIAN # define le64toh(x) htooe64(x) # else /* nothing to swap */ # define le64toh(x) (x) # endif #endif /* !le64toh */ #if !defined htobe64 # if BYTE_ORDER == BIG_ENDIAN # define htobe64(x) (x) # else # define htobe64(x) htooe64(x) # endif #endif /* !htobe64 */ #if !defined htole64 # if BYTE_ORDER == BIG_ENDIAN # define htole64(x) htooe64(x) # else /* no need swapping */ # define htole64(x) (x) # endif #endif /* !htole64 */ /* we could technically include byteswap.h and to the swap ourselves * in the missing cases. Instead we'll just leave it as is and wait * for bug reports. */ #endif /* INCLUDED_boops_h_ */ dateutils-0.4.5/lib/daisy.c000066400000000000000000000202561335042257000155470ustar00rootroot00000000000000/*** daisy.c -- guts for daisy dates * * Copyright (C) 2010-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of dateutils. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * **/ #define ASPECT_DAISY #include "nifty.h" #if !defined DEFUN # define DEFUN #endif /* !DEFUN */ #if !defined DAISY_ASPECT_HELPERS_ #define DAISY_ASPECT_HELPERS_ #define TO_BASE(x) ((x) - DT_DAISY_BASE_YEAR) #define TO_YEAR(x) ((x) + DT_DAISY_BASE_YEAR) static inline __attribute__((const, pure)) dt_daisy_t __jan00_daisy(unsigned int year) { /* daisy's base year is both 1 mod 4 and starts on a monday, so ... */ unsigned int by = TO_BASE(year); #if defined WITH_FAST_ARITH return by * 365U + by / 4U; #else /* !WITH_FAST_ARITH */ by = by * 365U + by / 4U; #if DT_DAISY_BASE_YEAR == 1917 if (UNLIKELY(year > 2100U)) { by -= (year - 2001U) / 100U; by += (year - 2001U) / 400U; } #elif DT_DAISY_BASE_YEAR == 1753 if (LIKELY(year > 1800U)) { by -= (year - 1701U) / 100U; by += (year - 1601U) / 400U; } #elif DT_DAISY_BASE_YEAR == 1601 by -= (year - 1601U) / 100U; by += (year - 1601U) / 400U; #endif return by; #endif /* WITH_FAST_ARITH */ } #endif /* DAISY_ASPECT_HELPERS_ */ #if defined ASPECT_GETTERS && !defined DAISY_ASPECT_GETTERS_ #define DAISY_ASPECT_GETTERS_ static __attribute__((const, pure)) dt_dow_t __daisy_get_wday(dt_daisy_t d) { /* daisy wdays are simple because the base year is chosen so that day 0 * in the daisy calendar is a sunday */ return (dt_dow_t)((d % GREG_DAYS_P_WEEK) ?: DT_SUNDAY); } static __attribute__((const, pure)) unsigned int __daisy_get_year(dt_daisy_t d) { /* given days since 1917-01-01 (Mon), compute a year */ unsigned int by; if (UNLIKELY(d == 0)) { return 0U; } /* get an estimate for the year and readjust */ by = d / 365U; if (UNLIKELY(TO_YEAR(by) > DT_MAX_YEAR)) { return 0U; } else if (UNLIKELY(__jan00_daisy(TO_YEAR(by)) >= d)) { by--; #if !defined WITH_FAST_ARITH if (UNLIKELY(__jan00_daisy(TO_YEAR(by)) >= d)) { by--; } #endif /* WITH_FAST_ARITH */ } return TO_YEAR(by); } static __attribute__((const, pure)) unsigned int __daisy_get_yday(dt_daisy_t d) { dt_daisy_t j00; unsigned int y; if (UNLIKELY(d == 0)) { return 0U; } y = __daisy_get_year(d); j00 = __jan00_daisy(y); return d - j00; } #endif /* DAISY_ASPECT_GETTERS_ */ #if defined ASPECT_CONV && !defined DAISY_ASPECT_CONV_ #define DAISY_ASPECT_CONV_ #if DT_DAISY_BASE_YEAR == 1917 # define DT_LDN_BASE (122068U/*lilian's 1917-01-00*/) # define DT_JDN_BASE (2421228.5f/*julian's 1917-01-00*/) # define DT_MDN_BASE (700170/*matlab's 1917-01-00*/) #elif DT_DAISY_BASE_YEAR == 1753 # define DT_LDN_BASE (62169U/*lilian's 1753-01-00*/) # define DT_JDN_BASE (2361329.5f/*julian's 1753-01-00*/) # define DT_MDN_BASE (640271/*matlab's 1753-01-00*/) #elif DT_DAISY_BASE_YEAR == 1601 # define DT_LDN_BASE (6652U/*lilian's 1601-01-00*/) # define DT_JDN_BASE (2305812.5f/*julian's 1601-01-00*/) # define DT_MDN_BASE (584754/*matlab's 1601-01-00*/) #else # error cannot convert to ldn, unknown base year #endif static __attribute__((const, pure)) dt_ldn_t __daisy_to_ldn(dt_daisy_t d) { return d + DT_LDN_BASE; } static __attribute__((const, pure)) dt_jdn_t __daisy_to_jdn(dt_daisy_t d) { return (dt_jdn_t)d + DT_JDN_BASE; } static __attribute__((const, pure)) dt_mdn_t __daisy_to_mdn(dt_daisy_t d) { return (dt_mdn_t)d + DT_MDN_BASE; } static __attribute__((const, pure)) dt_daisy_t __ldn_to_daisy(dt_ldn_t d) { dt_sdaisy_t tmp; if ((tmp = d - DT_LDN_BASE) > 0) { return (dt_daisy_t)tmp; } return 0U; } static __attribute__((const, pure)) dt_daisy_t __jdn_to_daisy(dt_jdn_t d) { float tmp; if ((tmp = d - DT_JDN_BASE) > 0.0f) { return (dt_daisy_t)tmp; } return 0U; } static __attribute__((const, pure)) dt_daisy_t __mdn_to_daisy(dt_mdn_t d) { dt_sdaisy_t tmp; if ((tmp = d - DT_MDN_BASE) > 0) { return (dt_daisy_t)tmp; } return 0U; } DEFUN __attribute__((const, pure)) dt_ymd_t __daisy_to_ymd(dt_daisy_t that) { dt_daisy_t j00; unsigned int doy; unsigned int y; struct __md_s md; if (UNLIKELY(that == 0)) { return (dt_ymd_t){.u = 0}; } else if (UNLIKELY(!(y = __daisy_get_year(that)))) { return (dt_ymd_t){.u = 0}; } j00 = __jan00_daisy(y); doy = that - j00; md = __yday_get_md(y, doy); #if defined HAVE_ANON_STRUCTS_INIT return (dt_ymd_t){.y = y, .m = md.m, .d = md.d}; #else /* !HAVE_ANON_STRUCTS_INIT */ { dt_ymd_t res; res.y = y; res.m = md.m; res.d = md.d; return res; } #endif /* HAVE_ANON_STRUCTS_INIT */ } static __attribute__((const, pure)) dt_ymcw_t __daisy_to_ymcw(dt_daisy_t that) { dt_ymd_t tmp; unsigned int c; unsigned int w; if (UNLIKELY(that == 0)) { return (dt_ymcw_t){.u = 0}; } tmp = __daisy_to_ymd(that); c = __ymd_get_count(tmp); w = __daisy_get_wday(that); #if defined HAVE_ANON_STRUCTS_INIT return (dt_ymcw_t){.y = tmp.y, .m = tmp.m, .c = c, .w = w}; #else { dt_ymcw_t res; res.y = tmp.y; res.m = tmp.m; res.c = c; res.w = w; return res; } #endif } static __attribute__((const, pure)) dt_ywd_t __daisy_to_ywd(dt_daisy_t that) { const unsigned int wd = (that + GREG_DAYS_P_WEEK - 1) % GREG_DAYS_P_WEEK; dt_dow_t dow = (dt_dow_t)(wd + 1U); unsigned int y = __daisy_get_year(that); int yd = that - __jan00_daisy(y); return __make_ywd_yd_dow(y, yd, dow); } static __attribute__((const, pure)) dt_yd_t __daisy_to_yd(dt_daisy_t d) { int yd = __daisy_get_yday(d); unsigned int y = __daisy_get_year(d); #if defined HAVE_ANON_STRUCTS_INIT return (dt_yd_t){.y = y, .d = yd}; #else dt_yd_t res; res.y = y; res.d = yd; return res; #endif } #endif /* ASPECT_CONV */ #if defined ASPECT_ADD && !defined DAISY_ASPECT_ADD_ #define DAISY_ASPECT_ADD_ #define ASPECT_GETTERS #include "daisy.c" #undef ASPECT_GETTERS static __attribute__((const, pure)) dt_daisy_t __daisy_add_d(dt_daisy_t d, int n) { /* add N days to D */ d += n; return d; } static __attribute__((const, pure)) dt_daisy_t __daisy_add_b(dt_daisy_t d, int n) { /* add N business days to D */ dt_dow_t dow = __daisy_get_wday(d); int equ = __get_d_equiv(dow, n); d += equ; return d; } static __attribute__((const, pure)) dt_daisy_t __daisy_add_w(dt_daisy_t d, int n) { /* add N weeks to D */ return __daisy_add_d(d, GREG_DAYS_P_WEEK * n); } #endif /* ASPECT_ADD */ #if defined ASPECT_DIFF && !defined DAISY_ASPECT_DIFF_ #define DAISY_ASPECT_DIFF_ static __attribute__((const, pure)) struct dt_ddur_s __daisy_diff(dt_daisy_t d1, dt_daisy_t d2) { /* compute d2 - d1 */ int32_t diff = d2 - d1; return dt_make_ddur(DT_DURD, diff); } #endif /* ASPECT_DIFF */ #if defined ASPECT_STRF && !defined DAISY_ASPECT_STRF_ #define DAISY_ASPECT_STRF_ DEFUN void __prep_strfd_daisy(struct strpd_s *tgt, dt_daisy_t d) { dt_ymd_t tmp = __daisy_to_ymd(d); tgt->y = tmp.y; tgt->m = tmp.m; tgt->d = tmp.d; return; } #endif /* ASPECT_STRF */ /* daisy.c ends here */ dateutils-0.4.5/lib/date-core-private.h000066400000000000000000000077331335042257000177630ustar00rootroot00000000000000/*** date-core-private.h -- our universe of dates, private bits * * Copyright (C) 2011-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of dateutils. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * **/ /* private portion of date-core.h */ #if !defined INCLUDED_date_core_private_h_ #define INCLUDED_date_core_private_h_ #include "date-core.h" /* formatting defaults */ extern const char ymd_dflt[]; extern const char ymcw_dflt[]; extern const char ywd_dflt[]; extern const char yd_dflt[]; extern const char daisy_dflt[]; extern const char bizsi_dflt[]; extern const char bizda_dflt[]; extern const char ymddur_dflt[]; extern const char ymcwdur_dflt[]; extern const char ywddur_dflt[]; extern const char yddur_dflt[]; extern const char daisydur_dflt[]; extern const char bizsidur_dflt[]; extern const char bizdadur_dflt[]; extern dt_dtyp_t __trans_dfmt_special(const char*); extern dt_dtyp_t __trans_dfmt(const char **fmt); extern dt_durtyp_t __trans_ddurfmt(const char**fmt); /** * Get the week count of D in the year when weeks start at _1st_wd. */ extern int __yd_get_wcnt(dt_yd_t d, dt_dow_t _1st_wd); /** * Like __yd_get_wcnt() but for ISO week convention. */ extern int __yd_get_wcnt_iso(dt_yd_t d); /** * Like __yd_get_wcnt() but disregard what day the year started with. */ extern int __yd_get_wcnt_abs(dt_yd_t d); /** * Return the N-th W-day in the year of THAT. * This is equivalent with 8601's Y-W-D calendar where W is the week * of the year and D the day in the week */ extern unsigned int __ymcw_get_yday(dt_ymcw_t that); /** * Get the number of days in month M of year Y. */ extern unsigned int __get_mdays(unsigned int y, unsigned int m); /** * Get the number of business days in month M of year Y. */ extern unsigned int __get_bdays(unsigned int y, unsigned int m); /** * Get the number of ISO weeks in year Y. */ extern unsigned int __get_isowk(unsigned int y); /** * Compare two ymcw objects, return <0, 0, >0 when D1 < D2, D1 == D2, D1 > D2 */ extern int __ymcw_cmp(dt_ymcw_t d1, dt_ymcw_t d2); /** * Get N where N is the N-th occurrence of wday in the month of that year */ extern unsigned int __ymd_get_count(dt_ymd_t that); /** * Crop dates with days beyond ultimo. */ extern __attribute__((pure)) dt_ymd_t __ymd_fixup(dt_ymd_t); extern __attribute__((pure)) dt_ywd_t __ywd_fixup(dt_ywd_t); extern __attribute__((pure)) dt_yd_t __yd_fixup(dt_yd_t); extern __attribute__((pure)) dt_ymcw_t __ymcw_fixup(dt_ymcw_t); extern __attribute__((pure)) dt_bizda_t __bizda_fixup(dt_bizda_t); #endif /* INCLUDED_date_core_private_h_ */ dateutils-0.4.5/lib/date-core-strpf.c000066400000000000000000000412721335042257000174360ustar00rootroot00000000000000/*** date-core-strpf.c -- parser and formatter funs for date-core * * Copyright (C) 2011-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of dateutils. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * **/ /* implementation part of date-core-strpf.h */ #if !defined INCLUDED_date_core_strpf_c_ #define INCLUDED_date_core_strpf_c_ #if defined HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include "strops.h" #include "token.h" #include "date-core.h" #include "date-core-strpf.h" #include "dt-locale.h" #if defined __INTEL_COMPILER /* we MUST return a char* */ # pragma warning (disable:2203) #elif defined __GNUC__ # pragma GCC diagnostic ignored "-Wcast-qual" #endif /* __INTEL_COMPILER */ #if !defined DEFUN # define DEFUN #endif /* !DEFUN */ #if !defined DEFVAR # define DEFVAR #endif /* !DEFVAR */ DEFUN struct dt_d_s __strpd_std(const char *str, char **ep) { /* code dupe, see __strpdt_std() */ struct dt_d_s res = dt_d_initialiser(); struct strpd_s d; const char *sp; if ((sp = str) == NULL) { goto out; } d = strpd_initialiser(); /* read the year */ d.y = strtoi(sp, &sp); if (d.y < DT_MIN_YEAR || d.y > DT_MAX_YEAR || *sp++ != '-') { goto fucked; } /* check for ywd dates */ if (UNLIKELY(*sp == 'W')) { /* brilliant */ sp++, d.c = strtoi(sp, &sp); if (d.c < 0 || d.c > 53 || *sp++ != '-') { goto fucked; } d.flags.c_wcnt_p = 1; d.flags.wk_cnt = YWD_ISOWK_CNT; goto dow; } /* read the month, then day count */ with (const char *tmp) { d.m = strtoi(sp, &tmp); if (d.m < 0 || d.m > 366) { goto fucked; } else if (UNLIKELY(*tmp != '-')) { /* oh, could be an ordinal date */ if (tmp - sp >= 3U) { d.d = d.m; d.m = 0U; d.flags.d_dcnt_p = 1U; } else if ((unsigned int)d.m <= GREG_MONTHS_P_YEAR) { ; } else { goto fucked; } sp = tmp; } else if (d.d = strtoi(++tmp, &sp), d.d < 0 || d.d > 31) { /* didn't work, fuck off */ goto fucked; } } /* check the date type */ switch (*sp) { case '-': /* it is a YMCW date */ if ((d.c = d.d) > 5) { /* nope, it was bollocks */ break; } d.d = 0; sp++; dow: if (d.w = strtoi(sp, &sp), d.w < 0 || (unsigned int)d.w > GREG_DAYS_P_WEEK) { /* didn't work, fuck off */ goto fucked; } /* fix up d.w right away */ d.w = d.w ?: DT_SUNDAY; break; case 'B': /* it's a bizda/YMDU before ultimo date */ d.flags.ab = BIZDA_BEFORE; case 'b': /* it's a bizda/YMDU after ultimo date */ d.flags.bizda = 1; d.b = d.d; d.d = 0; sp++; break; default: /* we don't care */ break; } /* guess what we're doing */ res = __guess_dtyp(d); out: if (ep != NULL) { *ep = (char*)sp; } return res; fucked: if (ep != NULL) { *ep = (char*)str; } return dt_d_initialiser(); } DEFUN int __strpd_card(struct strpd_s *d, const char *sp, struct dt_spec_s s, char **ep) { /* we're really pessimistic, aren't we? */ int res = -1; switch (s.spfl) { default: case DT_SPFL_UNK: break; case DT_SPFL_N_DSTD: d->y = strtoi_lim(sp, &sp, DT_MIN_YEAR, DT_MAX_YEAR); sp++; d->m = strtoi_lim(sp, &sp, 0, GREG_MONTHS_P_YEAR); sp++; d->d = strtoi_lim(sp, &sp, 0, 31); res = 0 - (d->y < 0 || d->m < 0 || d->d < 0); break; case DT_SPFL_N_YEAR: switch (s.abbr) { case DT_SPMOD_LONG: d->y = strtoi_lim(sp, &sp, DT_MIN_YEAR, DT_MAX_YEAR); break; case DT_SPMOD_NORM: d->y = strtoi_lim(sp, &sp, 0, 99); if (UNLIKELY(d->y < 0)) { break; } #if defined LIBDUT with (struct dt_d_s b = dt_get_dbase()) { unsigned int by = b.ymd.y - 50U; int c = by / 100U; int y = by % 100U; if (d->y < y) { c++; } d->y += c * 100; } #else /* !LIBDUT */ /* hardcode base as 2015-01-01 */ if ((d->y += 2000) > 2065) { d->y -= 100; } #endif /* LIBDUT */ break; case DT_SPMOD_ABBR: if (UNLIKELY((unsigned char)(*sp ^ '0') >= 10)) { d->y = -1; break; } d->y = (*sp++ ^ '0'); #if defined LIBDUT with (struct dt_d_s b = dt_get_dbase()) { unsigned int by = b.ymd.y; int c = by / 10U; int y = by % 10U; if (d->y < y) { c++; } d->y += c * 10; } #else /* !LIBDUT */ /* hardcode base as 2015-01-01 */ if ((d->y += 2010) < 2015) { d->y += 10; } #endif /* LIBDUT */ break; } res = 0 - (d->y < 0); break; case DT_SPFL_N_MON: d->m = strtoi_lim(sp, &sp, 0, GREG_MONTHS_P_YEAR); res = 0 - (d->m < 0); break; case DT_SPFL_N_DCNT_MON: /* ymd mode? */ if (LIKELY(!s.bizda)) { d->d = padstrtoi_lim(sp, &sp, 0, 31); res = 0 - (d->d < 0); } else { d->b = strtoi_lim(sp, &sp, 0, 23); res = 0 - (d->b < 0); } break; case DT_SPFL_N_DCNT_WEEK: /* ymcw mode? */ d->w = strtoi_lim(sp, &sp, 0, GREG_DAYS_P_WEEK); /* fix up d->w right away */ d->w = d->w ?: DT_SUNDAY; res = 0 - (d->w < 0); break; case DT_SPFL_N_WCNT_MON: /* ymcw mode? */ d->c = strtoi_lim(sp, &sp, 0, 5); res = 0 - (d->c < 0); break; case DT_SPFL_S_WDAY: /* ymcw mode? */ switch (s.abbr) { case DT_SPMOD_NORM: d->w = strtoarri( sp, &sp, dut_abbr_wday, dut_nabbr_wday); break; case DT_SPMOD_LONG: d->w = strtoarri( sp, &sp, dut_long_wday, dut_nlong_wday); break; case DT_SPMOD_ABBR: { const char *pos; if ((pos = strchr(dut_abab_wday, *sp++)) != NULL) { d->w = pos - dut_abab_wday; } else { d->w = -1; } break; } case DT_SPMOD_ILL: default: break; } res = 0 - (d->w < 0); break; case DT_SPFL_S_MON: switch (s.abbr) { case DT_SPMOD_NORM: d->m = strtoarri( sp, &sp, dut_abbr_mon, dut_nabbr_mon); break; case DT_SPMOD_LONG: d->m = strtoarri( sp, &sp, dut_long_mon, dut_nlong_mon); break; case DT_SPMOD_ABBR: { const char *pos; if ((pos = strchr(dut_abab_mon, *sp++)) != NULL) { d->m = pos - dut_abab_mon; } else { d->m = -1; } break; } case DT_SPMOD_ILL: default: break; } res = 0 - (d->m < 0); break; case DT_SPFL_S_QTR: if (*sp++ != 'Q') { break; } case DT_SPFL_N_QTR: if (d->m == 0) { int q; if ((q = strtoi_lim(sp, &sp, 1, 4)) >= 0) { d->m = q * 3 - 2; res = 0; } } break; case DT_SPFL_LIT_PERCENT: if (*sp++ == '%') { res = 0; } break; case DT_SPFL_LIT_TAB: if (*sp++ == '\t') { res = 0; } break; case DT_SPFL_LIT_NL: if (*sp++ == '\n') { res = 0; } break; case DT_SPFL_N_DCNT_YEAR: /* was %D and %j, cannot be used at the moment */ if ((d->d = strtoi_lim(sp, &sp, 1, 366)) >= 0) { res = 0; d->flags.d_dcnt_p = 1; } break; case DT_SPFL_N_WCNT_YEAR: /* was %C, cannot be used at the moment */ d->c = strtoi_lim(sp, &sp, 0, 53); d->flags.wk_cnt = s.wk_cnt; /* let everyone know d->c has a week-count in there */ d->flags.c_wcnt_p = 1; res = 0; break; } /* assign end pointer */ if (ep != NULL) { *ep = (char*)sp; } return res; } DEFUN int __strpd_rom(struct strpd_s *d, const char *sp, struct dt_spec_s s, char **ep) { int res = -1; switch (s.spfl) { default: case DT_SPFL_UNK: break; case DT_SPFL_N_YEAR: switch (s.abbr) { case DT_SPMOD_LONG: d->y = romstrtoi_lim( sp, &sp, DT_MIN_YEAR, DT_MAX_YEAR); break; case DT_SPMOD_NORM: d->y = romstrtoi_lim(sp, &sp, 0, 99); if (UNLIKELY(d->y < 0)) { ; } else if ((d->y += 2000) > 2068) { d->y -= 100; } break; case DT_SPMOD_ABBR: d->y = romstrtoi_lim(sp, &sp, 0, 9); if (UNLIKELY(d->y < 0)) { ; } else { d->y += 2010; } break; } res = 0 - (d->y < 0); break; case DT_SPFL_N_MON: d->m = romstrtoi_lim(sp, &sp, 0, GREG_MONTHS_P_YEAR); res = 0 - (d->m < 0); break; case DT_SPFL_N_DCNT_MON: d->d = romstrtoi_lim(sp, &sp, 0, 31); res = 0 - (d->d < 0); break; case DT_SPFL_N_WCNT_MON: d->c = romstrtoi_lim(sp, &sp, 0, 5); res = 0 - (d->c < 0); break; } if (ep != NULL) { *ep = (char*)sp; } return res; } #if defined __INTEL_COMPILER /* we MUST return a char* */ # pragma warning (default:2203) #elif defined __GNUC__ # pragma GCC diagnostic warning "-Wcast-qual" #endif /* __INTEL_COMPILER */ static void __strfd_get_md(struct strpd_s *d, struct dt_d_s this) { struct __md_s both = dt_get_md(this); d->m = both.m; d->d = both.d; return; } static void __strfd_get_m(struct strpd_s *d, struct dt_d_s this) { d->m = dt_get_mon(this); return; } static void __strfd_get_d(struct strpd_s *d, struct dt_d_s this) { d->d = dt_get_mday(this); return; } DEFUN size_t __strfd_card( char *buf, size_t bsz, struct dt_spec_s s, struct strpd_s *d, struct dt_d_s that) { size_t res = 0; switch (s.spfl) { default: case DT_SPFL_UNK: break; case DT_SPFL_N_DSTD: if (UNLIKELY(!d->m && (!d->d || d->flags.d_dcnt_p))) { __strfd_get_md(d, that); } else if (UNLIKELY(!d->d)) { __strfd_get_d(d, that); } if (LIKELY(bsz >= 10)) { ui9999topstr(buf + 0, bsz, d->y, 4, '0'); buf[4] = '-'; ui99topstr(buf + 5, bsz, d->m, 2, '0'); buf[7] = '-'; ui99topstr(buf + 8, bsz, d->d, 2, '0'); res = 10; } break; case DT_SPFL_N_YEAR: { unsigned int y = d->y; int prec; if (UNLIKELY(s.tai && d->flags.real_y_in_q)) { y = d->q; } else if (s.tai) { /* oh we want ISO week dates */ y = dt_dconv(DT_YWD, that).ywd.y; } switch (s.abbr) { case DT_SPMOD_LONG: prec = 4; break; case DT_SPMOD_NORM: prec = 2; break; case DT_SPMOD_ABBR: prec = 1; break; default: /* it's just bollocks */ return 0U; } res = ui9999topstr(buf, prec, y, 4U, padchar(s)); break; } case DT_SPFL_N_MON: if (UNLIKELY(!d->m && (!d->d || d->flags.d_dcnt_p))) { __strfd_get_md(d, that); } else if (UNLIKELY(!d->m)) { __strfd_get_m(d, that); } res = ui99topstr( buf, bsz, d->m, 2 - (s.pad == DT_SPPAD_OMIT), padchar(s)); break; case DT_SPFL_N_DCNT_MON: { /* ymd mode check? */ unsigned int pd; if (LIKELY(!s.bizda)) { if (UNLIKELY(!d->m && (!d->d || d->flags.d_dcnt_p))) { __strfd_get_md(d, that); } else if (UNLIKELY(!d->d)) { __strfd_get_d(d, that); } pd = d->d; } else { /* must be bizda now */ pd = dt_get_bday_q( that, __make_bizda_param(s.ab, BIZDA_ULTIMO)); } res = ui99topstr( buf, bsz, pd, 2 - (s.pad == DT_SPPAD_OMIT), padchar(s)); break; } case DT_SPFL_N_DCNT_WEEK: /* ymcw mode check */ with (unsigned int w = (unsigned)d->w ?: dt_get_wday(that)) { const unsigned int ymcwp = s.wk_cnt != YWD_MONWK_CNT; if (w == DT_SUNDAY && ymcwp) { /* turn Sun 07 to Sun 00 */ w = 0; } res = ui99topstr(buf, bsz, w, 1 + ymcwp, padchar(s)); } break; case DT_SPFL_N_WCNT_MON: { unsigned int c = d->c; /* ymcw mode check? */ if (!c || that.typ == DT_YWD) { /* don't store it */ c = (unsigned int)dt_get_wcnt_mon(that); } res = ui99topstr( buf, bsz, c, 2 - (s.pad == DT_SPPAD_OMIT), padchar(s)); break; } case DT_SPFL_S_WDAY: /* get the weekday in ymd mode!! */ d->w = d->w ? (dt_dow_t)d->w : dt_get_wday(that); switch (s.abbr) { case DT_SPMOD_NORM: res = arritostr( buf, bsz, d->w, duf_abbr_wday, dut_nabbr_wday); break; case DT_SPMOD_LONG: res = arritostr( buf, bsz, d->w, duf_long_wday, dut_nlong_wday); break; case DT_SPMOD_ABBR: /* super abbrev'd wday */ if (d->w < dut_nabab_wday) { buf[res++] = dut_abab_wday[d->w]; } break; case DT_SPMOD_ILL: default: break; } break; case DT_SPFL_S_MON: switch (s.abbr) { case DT_SPMOD_NORM: res = arritostr( buf, bsz, d->m, duf_abbr_mon, dut_nabbr_mon); break; case DT_SPMOD_LONG: res = arritostr( buf, bsz, d->m, duf_long_mon, dut_nlong_mon); break; case DT_SPMOD_ABBR: /* super abbrev'd month */ if (d->m < dut_nabab_mon) { buf[res++] = dut_abab_mon[d->m]; } break; case DT_SPMOD_ILL: default: break; } break; case DT_SPFL_S_QTR: buf[res++] = 'Q'; buf[res++] = (char)(dt_get_quarter(that) + '0'); break; case DT_SPFL_N_QTR: buf[res++] = '0'; buf[res++] = (char)(dt_get_quarter(that) + '0'); break; case DT_SPFL_LIT_PERCENT: /* literal % */ buf[res++] = '%'; break; case DT_SPFL_LIT_TAB: /* literal tab */ buf[res++] = '\t'; break; case DT_SPFL_LIT_NL: /* literal \n */ buf[res++] = '\n'; break; case DT_SPFL_N_DCNT_YEAR: switch (that.typ) { case DT_YMD: case DT_BIZDA: { /* %j */ int yd; if (LIKELY(!s.bizda)) { yd = __ymd_get_yday(that.ymd); } else { yd = __bizda_get_yday( that.bizda, __get_bizda_param(that)); } if (yd >= 0) { res = ui999topstr( buf, bsz, yd, 3 - (s.pad == DT_SPPAD_OMIT) << 1U, padchar(s)); } else { buf[res++] = '0'; buf[res++] = '0'; buf[res++] = '0'; } break; } case DT_YD: res = ui999topstr( buf, bsz, d->d, 3 - (s.pad == DT_SPPAD_OMIT) << 1U, padchar(s)); break; case DT_LDN: res = snprintf(buf, bsz, "%u", that.ldn); break; case DT_JDN: res = snprintf(buf, bsz, "%.6f", that.jdn); break; default: break; } break; case DT_SPFL_N_WCNT_YEAR: { int yw = dt_get_wcnt_year(that, s.wk_cnt); res = ui99topstr( buf, bsz, yw, 2 - (s.pad == DT_SPPAD_OMIT), padchar(s)); break; } } return res; } DEFUN size_t __strfd_rom( char *buf, size_t bsz, struct dt_spec_s s, struct strpd_s *d, struct dt_d_s that) { size_t res = 0; if (that.typ != DT_YMD) { /* not supported for non-ymds */ return res; } switch (s.spfl) { default: case DT_SPFL_UNK: break; case DT_SPFL_N_YEAR: switch (s.abbr) { case DT_SPMOD_LONG: res = ui32tostrrom(buf, bsz, d->y); break; case DT_SPMOD_NORM: res = ui32tostrrom(buf, bsz, d->y % 100); break; case DT_SPMOD_ABBR: res = ui32tostrrom(buf, bsz, d->y % 10); break; case DT_SPMOD_ILL: default: /* should be impossible */ break; } break; case DT_SPFL_N_MON: res = ui32tostrrom(buf, bsz, d->m); break; case DT_SPFL_N_DCNT_MON: res = ui32tostrrom(buf, bsz, d->d); break; case DT_SPFL_N_WCNT_MON: { unsigned int c = d->c; if (!c) { /* don't store the result */ c = (unsigned int)dt_get_wcnt_mon(that); } res = ui32tostrrom(buf, bsz, c); break; } } return res; } DEFUN size_t __strfd_dur( char *buf, size_t bsz, struct dt_spec_s s, struct strpd_s *d, struct dt_ddur_s UNUSED(that)) { size_t res = 0; switch (s.spfl) { default: case DT_SPFL_UNK: break; case DT_SPFL_N_DSTD: case DT_SPFL_N_DCNT_MON: res = snprintf(buf, bsz, "%d", d->sd); break; case DT_SPFL_N_YEAR: if (!d->y) { /* fill in for a mo, hack hack hack * we'll think about the consequences later */ d->y = __uidiv(d->m, GREG_MONTHS_P_YEAR); d->m = __uimod(d->m, GREG_MONTHS_P_YEAR); } res = snprintf(buf, bsz, "%d", d->y); break; case DT_SPFL_N_MON: res = snprintf(buf, bsz, "%d", d->m); break; case DT_SPFL_N_DCNT_WEEK: if (!d->w) { /* hack hack hack * we'll think about the consequences later */ d->w = __uidiv(d->d, GREG_DAYS_P_WEEK); d->d = __uimod(d->d, GREG_DAYS_P_WEEK); } res = snprintf(buf, bsz, "%d", d->w); break; case DT_SPFL_N_WCNT_MON: res = snprintf(buf, bsz, "%d", d->c); break; case DT_SPFL_S_WDAY: case DT_SPFL_S_MON: case DT_SPFL_S_QTR: case DT_SPFL_N_QTR: case DT_SPFL_N_DCNT_YEAR: case DT_SPFL_N_WCNT_YEAR: break; case DT_SPFL_LIT_PERCENT: /* literal % */ buf[res++] = '%'; break; case DT_SPFL_LIT_TAB: /* literal tab */ buf[res++] = '\t'; break; case DT_SPFL_LIT_NL: /* literal \n */ buf[res++] = '\n'; break; } return res; } #endif /* INCLUDED_date_core_strpf_c_ */ dateutils-0.4.5/lib/date-core-strpf.h000066400000000000000000000103321335042257000174340ustar00rootroot00000000000000/*** date-core-strpf.h -- parser and formatter funs for date-core * * Copyright (C) 2011-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of dateutils. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * **/ #if !defined INCLUDED_date_core_strpf_h_ #define INCLUDED_date_core_strpf_h_ #if defined __cplusplus extern "C" { #endif /* __cplusplus */ struct strpd_s { signed int y; signed int m; union { signed int d; signed int sd; }; signed int c; signed int w; /* general flags */ union { unsigned int u; struct { unsigned int ab:1; unsigned int bizda:1; unsigned int d_dcnt_p:1; unsigned int c_wcnt_p:1; unsigned int wk_cnt:2;/*%C,%W,%U,%V*/ unsigned int real_y_in_q:1; }; } flags; signed int b; signed int q; }; struct strpdi_s { signed int y; signed int m; signed int d; signed int w; signed int b; }; struct strprng_s { size_t min; size_t max; }; /* helpers */ static inline __attribute__((pure, const)) struct strpd_s strpd_initialiser(void) { #if defined HAVE_SLOPPY_STRUCTS_INIT static const struct strpd_s res = {}; #else static const struct strpd_s res; #endif /* HAVE_SLOPPY_STRUCTS_INIT */ return res; } static inline __attribute__((pure, const)) struct strpdi_s strpdi_initialiser(void) { #if defined HAVE_SLOPPY_STRUCTS_INIT static const struct strpdi_s res = {}; #else static const struct strpdi_s res; #endif /* HAVE_SLOPPY_STRUCTS_INIT */ return res; } #if defined INCLUDED_date_core_h_ /** * Populate TGT with duration information from DUR. */ extern void __fill_strpdi(struct strpdi_s *tgt, struct dt_d_s dur); /** * Parse STR with the standard parser, put the end of the parsed string in EP.*/ extern struct dt_d_s __strpd_std(const char *str, char **ep); /** * Given a strpd object D, try to construct a dt_d object. * Defined in date-core.c */ extern struct dt_d_s __guess_dtyp(struct strpd_s d); #endif /* INCLUDED_date_core_h_ */ /* self-explanatory funs, innit? */ extern int __strpd_card(struct strpd_s *d, const char *sp, struct dt_spec_s s, char **ep); extern int __strpd_rom(struct strpd_s *d, const char *sp, struct dt_spec_s s, char **ep); extern size_t __strfd_card( char *buf, size_t bsz, struct dt_spec_s s, struct strpd_s *d, struct dt_d_s that); extern size_t __strfd_rom( char *buf, size_t bsz, struct dt_spec_s s, struct strpd_s *d, struct dt_d_s that); extern size_t __strfd_dur( char *buf, size_t bsz, struct dt_spec_s s, struct strpd_s *d, struct dt_ddur_s that); /* specific formatters and parsers */ extern void __prep_strfd_ywd(struct strpd_s *tgt, dt_ywd_t d); extern void __prep_strfd_daisy(struct strpd_s *tgt, dt_daisy_t d); extern void __prep_strfd_bizda(struct strpd_s *tgt, dt_bizda_t d, dt_bizda_param_t bp); #if defined __cplusplus } #endif /* __cplusplus */ #endif /* INCLUDED_date_core_strpf_h_ */ dateutils-0.4.5/lib/date-core.c000066400000000000000000001103711335042257000162770ustar00rootroot00000000000000/*** date-core.c -- our universe of dates * * Copyright (C) 2011-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of dateutils. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * **/ /* implementation part of date-core.h */ #if !defined INCLUDED_date_core_c_ #define INCLUDED_date_core_c_ #if defined HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #include #include #include "date-core.h" #include "date-core-private.h" #include "strops.h" #include "token.h" #include "nifty.h" /* parsers and formatters */ #include "date-core-strpf.h" #if defined __INTEL_COMPILER /* we MUST return a char* */ # pragma warning (disable:2203) #elif defined __GNUC__ # pragma GCC diagnostic ignored "-Wcast-qual" #endif /* __INTEL_COMPILER */ #if !defined DEFUN # define DEFUN #endif /* !DEFUN */ #if !defined DEFVAR # define DEFVAR #endif /* !DEFVAR */ #if !defined assert # define assert(x) #endif /* !assert */ /* weekdays of the first day of the year, * 3 bits per year, times 10 years makes 1 uint32_t */ typedef struct { #define __JAN01_Y_PER_B (10) unsigned int y0:3; unsigned int y1:3; unsigned int y2:3; unsigned int y3:3; unsigned int y4:3; unsigned int y5:3; unsigned int y6:3; unsigned int y7:3; unsigned int y8:3; unsigned int y9:3; /* 2 bits left */ unsigned int rest:2; } __jan01_wday_block_t; struct __md_s { unsigned int m; unsigned int d; }; /* helpers */ #include "gmtime.h" /* bizda definitions, reference dates */ static __attribute__((unused)) const char *bizda_ult[] = {"ultimo", "ult"}; /* arithmetics helpers */ static inline unsigned int __uimod(signed int x, signed int m) { int res = x % m; return res >= 0 ? res : res + m; } static inline unsigned int __uidiv(signed int x, signed int m) { /* uidiv expects its counterpart (the mod) to be computed with __uimod */ int res = x / m; return x >= 0 ? res : x % m ? res - 1 : res; } /* helpers from the calendar files, don't define any aspect, so only * the helpers should get included */ #include "yd.c" #include "ymd.c" #include "ymcw.c" #include "ywd.c" #include "bizda.c" #include "daisy.c" #define ASPECT_GETTERS #include "yd.c" #include "ymd.c" #include "ymcw.c" #include "ywd.c" #include "bizda.c" #include "daisy.c" #undef ASPECT_GETTERS #define ASPECT_CONV #include "yd.c" #include "ymd.c" #include "ymcw.c" #include "ywd.c" #include "bizda.c" #include "daisy.c" #undef ASPECT_CONV /* converting accessors */ DEFUN int dt_get_year(struct dt_d_s that) { switch (that.typ) { case DT_YMD: return that.ymd.y; case DT_YMCW: return that.ymcw.y; case DT_DAISY: return __daisy_to_ymd(that.daisy).y; case DT_BIZDA: return that.bizda.y; default: case DT_DUNK: return 0; } } DEFUN int dt_get_mon(struct dt_d_s that) { switch (that.typ) { case DT_YMD: return that.ymd.m; case DT_YMCW: return that.ymcw.m; case DT_DAISY: return __daisy_to_ymd(that.daisy).m; case DT_BIZDA: return that.bizda.m; case DT_YWD: return __ywd_get_mon(that.ywd); default: case DT_DUNK: return 0; } } DEFUN dt_dow_t dt_get_wday(struct dt_d_s that) { switch (that.typ) { case DT_YMD: return __ymd_get_wday(that.ymd); case DT_YMCW: return __ymcw_get_wday(that.ymcw); case DT_DAISY: return __daisy_get_wday(that.daisy); case DT_BIZDA: return __bizda_get_wday(that.bizda); case DT_YWD: return __ywd_get_wday(that.ywd); default: case DT_DUNK: return DT_MIRACLEDAY; } } DEFUN int dt_get_mday(struct dt_d_s that) { if (LIKELY(that.typ == DT_YMD)) { return that.ymd.d; } switch (that.typ) { case DT_YMCW: return __ymcw_get_mday(that.ymcw); case DT_DAISY: return __daisy_to_ymd(that.daisy).d; case DT_BIZDA: return __bizda_get_mday(that.bizda);; case DT_YMD: /* to shut gcc up */ default: case DT_DUNK: return 0; } } static struct __md_s dt_get_md(struct dt_d_s that) { switch (that.typ) { default: return (struct __md_s){.m = 0, .d = 0}; case DT_YMD: return (struct __md_s){.m = that.ymd.m, .d = that.ymd.d}; case DT_YMCW: { unsigned int d = __ymcw_get_mday(that.ymcw); return (struct __md_s){.m = that.ymcw.m, .d = d}; } case DT_YWD: /* should have come through the GETTERS aspect */ return __ywd_get_md(that.ywd); case DT_YD: return __yd_get_md(that.yd); } } /* too exotic to be public, nope bug #81 needs it */ int dt_get_wcnt_mon(struct dt_d_s that) { if (LIKELY(that.typ == DT_YMCW)) { return that.ymcw.c; } switch (that.typ) { case DT_YMD: return __ymd_get_count(that.ymd); case DT_DAISY: return __ymd_get_count(__daisy_to_ymd(that.daisy)); case DT_BIZDA: return __bizda_get_count(that.bizda); case DT_YMCW: /* to shut gcc up */ case DT_YWD: return __ywd_get_wcnt_mon(that.ywd); default: case DT_DUNK: return 0; } } /* forward decl */ static dt_yd_t dt_conv_to_yd(struct dt_d_s this); DEFUN int dt_get_wcnt_year(struct dt_d_s this, unsigned int wkcnt_convention) { int res; switch (this.typ) { case DT_YMD: case DT_DAISY: case DT_YD: { dt_yd_t yd = dt_conv_to_yd(this); switch (wkcnt_convention) { default: case YWD_ABSWK_CNT: res = __yd_get_wcnt_abs(yd); break; case YWD_ISOWK_CNT: res = __yd_get_wcnt_iso(yd); break; case YWD_MONWK_CNT: case YWD_SUNWK_CNT: { /* using monwk_cnt is a minor trick * from = 1 = Mon or 0 = Sun */ dt_dow_t from; switch (wkcnt_convention) { case YWD_MONWK_CNT: from = DT_MONDAY; break; case YWD_SUNWK_CNT: from = DT_SUNDAY; break; default: /* huh? */ from = DT_MIRACLEDAY; break; } res = __yd_get_wcnt(yd, from); break; } } break; } case DT_YMCW: res = __ymcw_get_yday(this.ymcw); break; case DT_YWD: res = __ywd_get_wcnt_year(this.ywd, wkcnt_convention); break; default: res = 0; break; } return res; } DEFUN unsigned int dt_get_yday(struct dt_d_s that) { switch (that.typ) { case DT_YMD: return __ymd_get_yday(that.ymd); case DT_YMCW: return __ymcw_get_yday(that.ymcw); case DT_DAISY: return __daisy_get_yday(that.daisy); case DT_BIZDA: return __bizda_get_yday(that.bizda, __get_bizda_param(that)); case DT_YWD: return __ywd_get_yday(that.ywd); default: case DT_DUNK: return 0; } } DEFUN int dt_get_bday(struct dt_d_s that) { /* get N where N is the N-th business day after ultimo */ switch (that.typ) { case DT_BIZDA: { dt_bizda_param_t p = __get_bizda_param(that); if (p.ab == BIZDA_AFTER && p.ref == BIZDA_ULTIMO) { return that.bizda.bd; } else if (p.ab == BIZDA_BEFORE && p.ref == BIZDA_ULTIMO) { int mb = __get_bdays(that.bizda.y, that.bizda.m); return mb - that.bizda.bd; } return 0; } case DT_DAISY: that.ymd = __daisy_to_ymd(that.daisy); case DT_YMD: return __ymd_get_bday( that.ymd, __make_bizda_param(BIZDA_AFTER, BIZDA_ULTIMO)); case DT_YMCW: return __ymcw_get_bday( that.ymcw, __make_bizda_param(BIZDA_AFTER, BIZDA_ULTIMO)); default: case DT_DUNK: return 0; } } DEFUN int dt_get_bday_q(struct dt_d_s that, dt_bizda_param_t bp) { /* get N where N is the N-th business day Before/After REF */ switch (that.typ) { case DT_BIZDA: { dt_bizda_param_t thatp = __get_bizda_param(that); if (UNLIKELY(thatp.ref != bp.ref)) { ; } else if (thatp.ab == bp.ab) { return that.bizda.bd; } else { int mb = __get_bdays(that.bizda.y, that.bizda.m); return mb - that.bizda.bd; } return 0/*__bizda_to_bizda(that.bizda, ba, ref)*/; } case DT_DAISY: that.ymd = __daisy_to_ymd(that.daisy); case DT_YMD: return __ymd_get_bday(that.ymd, bp); case DT_YMCW: return __ymcw_get_bday(that.ymcw, bp); default: case DT_DUNK: return 0; } } DEFUN int dt_get_quarter(struct dt_d_s that) { int m; switch (that.typ) { case DT_YMD: m = that.ymd.m; break; case DT_YMCW: m = that.ymcw.m; break; case DT_BIZDA: m = that.bizda.m; break; default: case DT_DUNK: return 0; } return (m - 1) / 3 + 1; } /* converters */ DEFUN dt_daisy_t dt_conv_to_daisy(struct dt_d_s that) { switch (that.typ) { case DT_DAISY: return that.daisy; case DT_YMD: return __ymd_to_daisy(that.ymd); case DT_YMCW: return __ymcw_to_daisy(that.ymcw); case DT_YWD: return __ywd_to_daisy(that.ywd); case DT_BIZDA: return __bizda_to_daisy(that.bizda, __get_bizda_param(that)); case DT_LDN: return __ldn_to_daisy(that.ldn); case DT_JDN: return __jdn_to_daisy(that.jdn); case DT_MDN: return __mdn_to_daisy(that.mdn); case DT_YD: return __yd_to_daisy(that.yd); case DT_DUNK: default: break; } return (dt_daisy_t)0; } static dt_ymd_t dt_conv_to_ymd(struct dt_d_s that) { switch (that.typ) { case DT_YMD: return that.ymd; case DT_YMCW: return __ymcw_to_ymd(that.ymcw); case DT_JDN: that.daisy = __jdn_to_daisy(that.jdn); goto daisy; case DT_LDN: that.daisy = __ldn_to_daisy(that.ldn); goto daisy; case DT_MDN: that.daisy = __mdn_to_daisy(that.mdn); goto daisy; case DT_DAISY: daisy: return __daisy_to_ymd(that.daisy); case DT_BIZDA: return __bizda_to_ymd(that.bizda); case DT_YWD: return __ywd_to_ymd(that.ywd); case DT_YD: return __yd_to_ymd(that.yd); case DT_DUNK: default: break; } return (dt_ymd_t){.u = 0}; } static dt_ymcw_t dt_conv_to_ymcw(struct dt_d_s that) { switch (that.typ) { case DT_YMD: return __ymd_to_ymcw(that.ymd); case DT_YMCW: return that.ymcw; case DT_JDN: that.daisy = __jdn_to_daisy(that.jdn); goto daisy; case DT_LDN: that.daisy = __ldn_to_daisy(that.ldn); goto daisy; case DT_MDN: that.daisy = __mdn_to_daisy(that.mdn); goto daisy; case DT_DAISY: daisy: return __daisy_to_ymcw(that.daisy); case DT_BIZDA: return __bizda_to_ymcw(that.bizda, __get_bizda_param(that)); case DT_YWD: return __ywd_to_ymcw(that.ywd); case DT_YD: return __yd_to_ymcw(that.yd); case DT_DUNK: default: break; } return (dt_ymcw_t){.u = 0}; } static dt_bizda_t dt_conv_to_bizda(struct dt_d_s that) { /* the problem with this conversion is that not all dates can be mapped * to a bizda date, so we need a policy first what to do in case things * go massively pear-shaped. */ switch (that.typ) { case DT_BIZDA: return that.bizda; case DT_YMD: break; case DT_YMCW: break; case DT_DAISY: break; case DT_YD: break; case DT_DUNK: default: break; } return (dt_bizda_t){.u = 0}; } static dt_ywd_t dt_conv_to_ywd(struct dt_d_s this) { switch (this.typ) { case DT_YWD: /* yay, that was quick */ return this.ywd; case DT_YMD: return __ymd_to_ywd(this.ymd); case DT_YMCW: return __ymcw_to_ywd(this.ymcw); case DT_JDN: this.daisy = __jdn_to_daisy(this.jdn); goto daisy; case DT_LDN: this.daisy = __ldn_to_daisy(this.ldn); goto daisy; case DT_MDN: this.daisy = __mdn_to_daisy(this.mdn); goto daisy; case DT_DAISY: daisy: return __daisy_to_ywd(this.daisy); case DT_BIZDA: return __bizda_to_ywd(this.bizda, __get_bizda_param(this)); case DT_YD: return __yd_to_ywd(this.yd); case DT_DUNK: default: break; } return (dt_ywd_t){.u = 0}; } static dt_yd_t dt_conv_to_yd(struct dt_d_s this) { switch (this.typ) { case DT_YD: /* yay, that was quick */ return this.yd; case DT_YMD: return __ymd_to_yd(this.ymd); case DT_JDN: this.daisy = __jdn_to_daisy(this.jdn); goto daisy; case DT_LDN: this.daisy = __ldn_to_daisy(this.ldn); goto daisy; case DT_MDN: this.daisy = __mdn_to_daisy(this.mdn); goto daisy; case DT_DAISY: daisy: return __daisy_to_yd(this.daisy); case DT_YMCW: return __ymcw_to_yd(this.ymcw); case DT_YWD: return __ywd_to_yd(this.ywd); default: break; } return (dt_yd_t){.u = 0}; } /* arithmetic */ #define ASPECT_ADD #include "yd.c" #include "ymd.c" #include "ymcw.c" #include "ywd.c" #include "bizda.c" #include "daisy.c" #undef ASPECT_ADD #define ASPECT_DIFF #include "yd.c" #include "ymd.c" #include "ymcw.c" #include "ywd.c" #include "bizda.c" #include "daisy.c" #undef ASPECT_DIFF #define ASPECT_CMP #include "yd.c" #include "ymd.c" #include "ymcw.c" #include "ywd.c" #include "bizda.c" #include "daisy.c" #undef ASPECT_CMP /* guessing parsers */ #include "strops.h" #include "token.h" #include "date-core-strpf.c" #if !defined SKIP_LEAP_ARITH /* we assume this file is in the dist, it's gen'd from fmt-special.gperf */ # include "fmt-special.c" #endif /* SKIP_LEAP_ARITH */ DEFVAR const char ymd_dflt[] = "%F"; DEFVAR const char ymcw_dflt[] = "%Y-%m-%c-%w"; DEFVAR const char ywd_dflt[] = "%G-W%V-%u"; DEFVAR const char yd_dflt[] = "%Y-%D"; DEFVAR const char daisy_dflt[] = "%d"; DEFVAR const char bizsi_dflt[] = "%db"; DEFVAR const char bizda_dflt[] = "%Y-%m-%db"; DEFVAR const char ymddur_dflt[] = "%Y-%0m-%0d"; DEFVAR const char ymcwdur_dflt[] = "%Y-%0m-%0w-%0d"; DEFVAR const char ywddur_dflt[] = "%G-W%0w-%d"; DEFVAR const char yddur_dflt[] = "%Y-%0d"; DEFVAR const char daisydur_dflt[] = "%d"; DEFVAR const char bizsidur_dflt[] = "%db"; DEFVAR const char bizdadur_dflt[] = "%Y-%0m-%0db"; DEFUN dt_dtyp_t __trans_dfmt_special(const char *fmt) { #if !defined SKIP_LEAP_ARITH size_t len = strlen(fmt); const struct dt_fmt_special_s *res; if (UNLIKELY((res = __fmt_special(fmt, len)) != NULL)) { return res->e; } #else /* SKIP_LEAP_ARITH */ (void)fmt; #endif /* !SKIP_LEAP_ARITH */ return DT_DUNK; } DEFUN dt_dtyp_t __trans_dfmt(const char **fmt) { if (UNLIKELY(*fmt == NULL)) { /* great, standing ovations to the user */ ; } else if (LIKELY(**fmt == '%')) { /* don't worry about it */ ; } else { const dt_dtyp_t tmp = __trans_dfmt_special(*fmt); switch (tmp) { default: break; case DT_YMD: *fmt = ymd_dflt; break; case DT_YMCW: *fmt = ymcw_dflt; break; case DT_YWD: *fmt = ywd_dflt; break; case DT_YD: *fmt = yd_dflt; break; case DT_BIZDA: *fmt = bizda_dflt; break; case DT_DAISY: *fmt = daisy_dflt; break; case DT_BIZSI: *fmt = bizsi_dflt; break; } return tmp; } return DT_DUNK; } DEFUN dt_durtyp_t __trans_ddurfmt(const char **fmt) { if (UNLIKELY(*fmt == NULL)) { /* great, standing ovations to the user */ ; } else if (LIKELY(**fmt == '%')) { /* don't worry about it */ ; } else { unsigned int tmp = __trans_dfmt_special(*fmt); switch (tmp) { default: break; case DT_YMD: *fmt = ymddur_dflt; tmp = DT_DURYMD; break; case DT_YMCW: *fmt = ymcwdur_dflt; tmp = DT_DURYMCW; break; case DT_YWD: *fmt = ywddur_dflt; tmp = DT_DURYWD; break; case DT_YD: *fmt = yddur_dflt; tmp = DT_DURYD; break; case DT_BIZDA: *fmt = bizdadur_dflt; tmp = DT_DURBIZDA; break; case DT_DAISY: *fmt = daisydur_dflt; tmp = DT_DURD; break; case DT_BIZSI: *fmt = bizsidur_dflt; tmp = DT_DURBD; break; } return (dt_durtyp_t)tmp; } return DT_DURUNK; } /* strpf glue */ DEFUN struct dt_d_s __guess_dtyp(struct strpd_s d) { struct dt_d_s res = dt_d_initialiser(); if (LIKELY(d.y > 0 && d.c <= 0 && !d.flags.c_wcnt_p && !d.flags.bizda)) { /* nearly all goes to ymd */ res.typ = DT_YMD; res.ymd.y = d.y; if (LIKELY(!d.flags.d_dcnt_p)) { #if defined WITH_FAST_ARITH res.ymd.d = d.d; #else /* !WITH_FAST_ARITH */ unsigned int md = __get_mdays(d.y, d.m); /* check for illegal dates, like 31st of April */ if ((res.ymd.d = d.d) > md) { res.ymd.d = md; res.fix = 1U; } #endif /* !WITH_FAST_ARITH */ /* month is always pertained */ res.ymd.m = d.m; } else { /* produce yd dates */ res.typ = DT_YD; res.yd.y = d.y; #if defined WITH_FAST_ARITH res.yd.d = d.d; #else /* !WITH_FAST_ARITH */ with (int maxd = __get_ydays(d.y)) { if (UNLIKELY((res.yd.d = d.d) > maxd)) { res.yd.d = maxd; } } #endif /* WITH_FAST_ARITH */ } } else if (d.y > 0 && d.m <= 0 && !d.flags.bizda) { res.typ = DT_YWD; res.ywd = __make_ywd_c(d.y, d.c, (dt_dow_t)d.w, d.flags.wk_cnt); } else if (d.y > 0 && !d.flags.bizda) { /* its legit for d.w to be naught */ res.typ = DT_YMCW; res.ymcw.y = d.y; res.ymcw.m = d.m; #if defined WITH_FAST_ARITH res.ymcw.c = d.c; #else /* !WITH_FAST_ARITH */ if (UNLIKELY((res.ymcw.c = d.c) >= 5)) { /* the user meant the LAST wday actually */ res.ymcw.c = __get_mcnt(d.y, d.m, (dt_dow_t)d.w); } #endif /* WITH_FAST_ARITH */ res.ymcw.w = d.w; } else if (d.y > 0 && d.flags.bizda) { /* d.c can be legit'ly naught */ dt_bizda_param_t bp = __make_bizda_param(d.flags.ab, 0); res.param = bp.u; res.typ = DT_BIZDA; res.bizda.y = d.y; res.bizda.m = d.m; #if defined WITH_FAST_ARITH res.bizda.bd = d.b; #else /* !WITH_FAST_ARITH */ unsigned int bd = __get_bdays(d.y, d.m); if ((res.bizda.bd = d.b) > bd) { res.bizda.bd = bd; res.fix = 1U; } #endif /* WITH_FAST_ARITH */ } else { /* anything else is bollocks for now */ ; } return res; } /* parser implementations */ #if defined __INTEL_COMPILER /* we MUST return a char* */ # pragma warning (disable:2203) #elif defined __GNUC__ # pragma GCC diagnostic ignored "-Wcast-qual" #endif /* __INTEL_COMPILER */ DEFUN struct dt_d_s dt_strpd(const char *str, const char *fmt, char **ep) { struct dt_d_s res = dt_d_initialiser(); struct strpd_s d = strpd_initialiser(); const char *sp = str; const char *fp; if (UNLIKELY(fmt == NULL)) { return __strpd_std(str, ep); } /* translate high-level format names */ __trans_dfmt(&fmt); fp = fmt; while (*fp && *sp) { const char *fp_sav = fp; struct dt_spec_s spec = __tok_spec(fp_sav, &fp); if (spec.spfl == DT_SPFL_UNK) { /* must be literal */ if (*fp_sav != *sp++) { sp = str; goto out; } } else if (LIKELY(!spec.rom)) { const char *sp_sav = sp; if (__strpd_card(&d, sp, spec, (char**)&sp) < 0) { sp = str; goto out; } if (spec.ord && __ordinalp(sp_sav, sp - sp_sav, (char**)&sp) < 0) { ; } if (spec.bizda) { switch (*sp++) { case 'B': d.flags.ab = BIZDA_BEFORE; case 'b': d.flags.bizda = 1; break; default: /* it's a bizda anyway */ d.flags.bizda = 1; sp--; break; } } } else if (UNLIKELY(spec.rom)) { if (__strpd_rom(&d, sp, spec, (char**)&sp) < 0) { sp = str; goto out; } } } res = __guess_dtyp(d); out: /* set the end pointer */ if (ep != NULL) { *ep = (char*)sp; } return res; } #define ASPECT_STRF #include "yd.c" #include "ymd.c" #include "ymcw.c" #include "ywd.c" #include "bizda.c" #include "daisy.c" #undef ASPECT_STRF DEFUN size_t dt_strfd(char *restrict buf, size_t bsz, const char *fmt, struct dt_d_s that) { struct strpd_s d = strpd_initialiser(); const char *fp; char *bp; dt_dtyp_t tgttyp; int set_fmt = 0; if (UNLIKELY(buf == NULL || bsz == 0)) { return 0; } if (LIKELY(fmt == NULL)) { /* um, great */ set_fmt = 1; } else if (LIKELY(*fmt == '%')) { /* don't worry about it */ ; } else if ((tgttyp = __trans_dfmt_special(fmt)) != DT_DUNK) { that = dt_dconv(tgttyp, that); set_fmt = 1; } if (set_fmt) { switch (that.typ) { case DT_YMD: fmt = ymd_dflt; break; case DT_YMCW: fmt = ymcw_dflt; break; case DT_YWD: fmt = ywd_dflt; break; case DT_YD: fmt = yd_dflt; break; case DT_DAISY: /* subject to change */ fmt = ymd_dflt; break; case DT_BIZDA: fmt = bizda_dflt; break; default: /* fuck */ abort(); break; } } switch (that.typ) { case DT_YMD: d.y = that.ymd.y; d.m = that.ymd.m; d.d = that.ymd.d; break; case DT_YMCW: d.y = that.ymcw.y; d.m = that.ymcw.m; d.c = that.ymcw.c; d.w = that.ymcw.w; break; case DT_YD: d.y = that.yd.y; d.d = that.yd.d; d.flags.d_dcnt_p = 1U; break; case DT_JDN: that.typ = DT_DAISY; that.daisy = __jdn_to_daisy(that.jdn); goto daisy_prep; case DT_LDN: that.typ = DT_DAISY; that.daisy = __ldn_to_daisy(that.ldn); goto daisy_prep; case DT_MDN: that.typ = DT_DAISY; that.daisy = __mdn_to_daisy(that.mdn); goto daisy_prep; case DT_DAISY: daisy_prep: __prep_strfd_daisy(&d, that.daisy); break; case DT_BIZDA: __prep_strfd_bizda(&d, that.bizda, __get_bizda_param(that)); break; case DT_YWD: __prep_strfd_ywd(&d, that.ywd); break; default: case DT_DUNK: bp = buf; goto out; } /* assign and go */ bp = buf; fp = fmt; for (char *const eo = buf + bsz; *fp && bp < eo;) { const char *fp_sav = fp; struct dt_spec_s spec = __tok_spec(fp_sav, &fp); if (spec.spfl == DT_SPFL_UNK) { /* must be literal then */ *bp++ = *fp_sav; } else if (LIKELY(!spec.rom)) { bp += __strfd_card(bp, eo - bp, spec, &d, that); if (spec.ord) { bp += __ordtostr(bp, eo - bp); } else if (spec.bizda) { /* don't print the b after an ordinal */ if (spec.ab == BIZDA_AFTER) { *bp++ = 'b'; } else { *bp++ = 'B'; } } } else if (UNLIKELY(spec.rom)) { bp += __strfd_rom(bp, eo - bp, spec, &d, that); } } if (bp < buf + bsz) { out: *bp = '\0'; } return bp - buf; } DEFUN struct dt_ddur_s dt_strpddur(const char *str, char **ep) { /* at the moment we allow only one format */ struct dt_ddur_s res = dt_make_ddur(DT_DURUNK, 0); const char *sp = str; long int tmp; if (str == NULL) { goto out; } /* read off co-class indicator */ if (*sp == '/') { res.cocl = 1U; sp++; } /* read just one component, use rudi's errno trick */ errno = 0; if ((tmp = strtol(str, (char**)&sp, 10)) == 0 && str == sp) { /* didn't work aye? */ goto out; } else if (tmp > INT_MAX || errno) { errno = ERANGE; goto out; } switch (*sp++) { case '\0': /* must have been day then */ res.durtyp = DT_DURD; sp--; break; case 'd': case 'D': res.durtyp = DT_DURD; break; case 'y': case 'Y': res.durtyp = DT_DURYR; break; case 'm': case 'M': res.durtyp = DT_DURMO; break; case 'w': case 'W': res.durtyp = DT_DURWK; break; case 'b': case 'B': res.durtyp = DT_DURBD; break; case 'q': case 'Q': res.durtyp = DT_DURQU; break; default: sp = str; goto out; } /* no further checks on TMP */ res.dv = tmp; out: if (ep != NULL) { *ep = (char*)sp; } return res; } DEFUN size_t dt_strfddur(char *restrict buf, size_t bsz, const char *fmt, struct dt_ddur_s that) { struct strpd_s d = strpd_initialiser(); const char *fp; char *bp; if (UNLIKELY(buf == NULL || bsz == 0)) { return 0; } switch (that.durtyp) { case DT_DURYMD: d.y = that.ymd.y; d.m = that.ymd.m; d.d = that.ymd.d; if (fmt == NULL) { fmt = ymddur_dflt; } break; case DT_DURYMCW: d.y = that.ymcw.y; d.m = that.ymcw.m; d.c = that.ymcw.c; d.d = that.ymcw.w; if (fmt == NULL) { fmt = ymcwdur_dflt; } break; case DT_DURYWD: d.y = that.ywd.y; d.c = that.ywd.c; d.d = that.ywd.w; if (fmt == NULL) { fmt = ywddur_dflt; } break; case DT_DURYD: d.y = that.yd.y; d.d = that.yd.d; if (fmt == NULL) { fmt = yddur_dflt; } break; case DT_DURBIZDA:; dt_bizda_param_t bparam; bparam.bs = that.param; d.y = that.bizda.y; d.m = that.bizda.m; d.b = that.bizda.bd; if (LIKELY(bparam.ab == BIZDA_AFTER)) { d.flags.ab = BIZDA_AFTER; } else { d.flags.ab = BIZDA_BEFORE; } d.flags.bizda = 1; if (fmt == NULL) { fmt = bizdadur_dflt; } break; case DT_DURD: case DT_DURBD: case DT_DURWK: case DT_DURMO: case DT_DURQU: case DT_DURYR: if (that.dv >= 0) { /* make sure the neg bit doesn't bite us */ that.dv = -that.dv; that.neg = 1U; } switch (that.durtyp) { case DT_DURD: d.d = that.dv; break; case DT_DURBD: d.b = that.dv; break; case DT_DURWK: d.d = that.dv * GREG_DAYS_P_WEEK; break; case DT_DURMO: d.m = that.dv; break; case DT_DURQU: d.m = that.dv * 3U; break; case DT_DURYR: d.y = that.dv; break; } break; default: case DT_DUNK: bp = buf; goto out; } /* translate high-level format names */ __trans_ddurfmt(&fmt); /* assign and go */ bp = buf; fp = fmt; if (that.neg) { *bp++ = '-'; } for (char *const eo = buf + bsz; *fp && bp < eo;) { const char *fp_sav = fp; struct dt_spec_s spec = __tok_spec(fp_sav, &fp); if (spec.spfl == DT_SPFL_UNK) { /* must be literal then */ *bp++ = *fp_sav; } else if (LIKELY(!spec.rom)) { bp += __strfd_dur(bp, eo - bp, spec, &d, that); if (spec.bizda) { /* don't print the b after an ordinal */ if (d.flags.ab == BIZDA_AFTER) { *bp++ = 'b'; } else { *bp++ = 'B'; } } } } if (bp < buf + bsz) { out: *bp = '\0'; } return bp - buf; } #if defined __INTEL_COMPILER /* we MUST return a char* */ # pragma warning (default:2203) #elif defined __GNUC__ # pragma GCC diagnostic warning "-Wcast-qual" #endif /* __INTEL_COMPILER */ /* date getters, platform dependent */ DEFUN struct dt_d_s dt_date(dt_dtyp_t outtyp) { struct dt_d_s res; time_t t = time(NULL); switch ((res.typ = outtyp)) { case DT_YMD: case DT_YMCW: case DT_YWD: case DT_YD: { struct tm tm; ffff_gmtime(&tm, t); switch (res.typ) { case DT_YMD: res.ymd.y = tm.tm_year; res.ymd.m = tm.tm_mon; res.ymd.d = tm.tm_mday; break; case DT_YMCW: { #if defined HAVE_ANON_STRUCTS_INIT dt_ymd_t tmp = { .y = tm.tm_year, .m = tm.tm_mon, .d = tm.tm_mday, }; #else dt_ymd_t tmp; tmp.y = tm.tm_year, tmp.m = tm.tm_mon, tmp.d = tm.tm_mday, #endif res.ymcw.y = tm.tm_year; res.ymcw.m = tm.tm_mon; res.ymcw.c = __ymd_get_count(tmp); res.ymcw.w = tm.tm_wday; break; } case DT_YD: res.yd.y = tm.tm_year; res.yd.d = tm.tm_yday; break; case DT_YWD: /* use ordinary conversion to ywd */ res.typ = DT_YMD; res.ymd.y = tm.tm_year; res.ymd.m = tm.tm_mon; res.ymd.d = tm.tm_mday; res = dt_dconv(DT_YWD, res); break; default: break; } break; } case DT_DAISY: /* time_t's base is 1970-01-01, which is daisy 19359 */ res.daisy = t / 86400 + 19359; break; /* the rest doesn't make sense I say */ default: case DT_DUNK: res.u = 0; } return res; } DEFUN struct dt_d_s dt_dconv(dt_dtyp_t tgttyp, struct dt_d_s d) { struct dt_d_s res = dt_d_initialiser(); /* fix up before conversion */ d = dt_dfixup(d); switch ((res.typ = tgttyp)) { case DT_YMD: res.ymd = dt_conv_to_ymd(d); break; case DT_YMCW: res.ymcw = dt_conv_to_ymcw(d); break; case DT_DAISY: case DT_JDN: case DT_LDN: case DT_MDN: { dt_daisy_t tmp = dt_conv_to_daisy(d); switch (tgttyp) { case DT_DAISY: res.daisy = tmp; break; case DT_LDN: res.ldn = __daisy_to_ldn(tmp); break; case DT_JDN: res.jdn = __daisy_to_jdn(tmp); break; case DT_MDN: res.mdn = __daisy_to_mdn(tmp); break; default: /* nice one gcc */ ; } break; } case DT_BIZDA: /* actually this is a parametrised date */ res.bizda = dt_conv_to_bizda(d); break; case DT_YWD: res.ywd = dt_conv_to_ywd(d); break; case DT_YD: res.yd = dt_conv_to_yd(d); break; case DT_DUNK: default: res.typ = DT_DUNK; break; } return res; } DEFUN struct dt_d_s dt_dadd_d(struct dt_d_s d, int n) { /* add N (gregorian) days to D */ if (UNLIKELY(!n)) { /* cacn't use short-cut return here, it'd upset the IPO/LTO */ goto out; } switch (d.typ) { case DT_JDN: d.daisy = __jdn_to_daisy(d.jdn); goto daisy_add_d; case DT_LDN: d.daisy = __ldn_to_daisy(d.ldn); goto daisy_add_d; case DT_MDN: d.daisy = __mdn_to_daisy(d.mdn); goto daisy_add_d; case DT_DAISY: daisy_add_d: d.daisy = __daisy_add_d(d.daisy, n); /* transform back (maybe) */ switch (d.typ) { case DT_DAISY: default: break; case DT_LDN: d.ldn = __daisy_to_ldn(d.daisy); break; case DT_JDN: d.jdn = __daisy_to_jdn(d.daisy); break; case DT_MDN: d.mdn = __daisy_to_mdn(d.daisy); break; } break; case DT_YMD: d.ymd = __ymd_add_d(d.ymd, n); break; case DT_YMCW: d.ymcw = __ymcw_add_d(d.ymcw, n); break; case DT_BIZDA: d.bizda = __bizda_add_d(d.bizda, n); break; case DT_YWD: d.ywd = __ywd_add_d(d.ywd, n); break; case DT_YD: d.yd = __yd_add_d(d.yd, n); break; case DT_DUNK: default: d.typ = DT_DUNK; d.u = 0; break; } out: return d; } DEFUN struct dt_d_s dt_dadd_b(struct dt_d_s d, int n) { /* add N business days to D */ if (UNLIKELY(!n)) { /* cacn't use short-cut return here, it'd upset the IPO/LTO */ goto out; } switch (d.typ) { case DT_JDN: d.daisy = __jdn_to_daisy(d.jdn); goto daisy_add_b; case DT_LDN: d.daisy = __ldn_to_daisy(d.ldn); goto daisy_add_b; case DT_MDN: d.daisy = __mdn_to_daisy(d.mdn); goto daisy_add_b; case DT_DAISY: daisy_add_b: d.daisy = __daisy_add_b(d.daisy, n); /* transform back (maybe) */ switch (d.typ) { case DT_DAISY: default: break; case DT_LDN: d.ldn = __daisy_to_ldn(d.daisy); break; case DT_JDN: d.jdn = __daisy_to_jdn(d.daisy); break; case DT_MDN: d.mdn = __daisy_to_mdn(d.daisy); break; } break; case DT_YMD: d.ymd = __ymd_add_b(d.ymd, n); break; case DT_YMCW: d.ymcw = __ymcw_add_b(d.ymcw, n); break; case DT_BIZDA: d.bizda = __bizda_add_b(d.bizda, n); break; case DT_YWD: d.ywd = __ywd_add_b(d.ywd, n); break; case DT_YD: d.yd = __yd_add_b(d.yd, n); break; case DT_DUNK: default: d.typ = DT_DUNK; d.u = 0; break; } out: return d; } DEFUN struct dt_d_s dt_dadd_w(struct dt_d_s d, int n) { /* add N weeks to D */ if (UNLIKELY(!n)) { /* cacn't use short-cut return here, it'd upset the IPO/LTO */ goto out; } switch (d.typ) { case DT_JDN: d.daisy = __jdn_to_daisy(d.jdn); goto daisy_add_w; case DT_LDN: d.daisy = __ldn_to_daisy(d.ldn); goto daisy_add_w; case DT_MDN: d.daisy = __mdn_to_daisy(d.mdn); goto daisy_add_w; case DT_DAISY: daisy_add_w: d.daisy = __daisy_add_w(d.daisy, n); /* transform back (maybe) */ switch (d.typ) { case DT_DAISY: default: break; case DT_LDN: d.ldn = __daisy_to_ldn(d.daisy); break; case DT_JDN: d.jdn = __daisy_to_jdn(d.daisy); break; case DT_MDN: d.mdn = __daisy_to_mdn(d.daisy); break; } break; case DT_YMD: d.ymd = __ymd_add_w(d.ymd, n); break; case DT_YMCW: d.ymcw = __ymcw_add_w(d.ymcw, n); break; case DT_BIZDA: d.bizda = __bizda_add_w(d.bizda, n); break; case DT_YWD: d.ywd = __ywd_add_w(d.ywd, n); break; case DT_YD: d.yd = __yd_add_w(d.yd, n); break; case DT_DUNK: default: d.typ = DT_DUNK; d.u = 0; break; } out: return d; } DEFUN struct dt_d_s dt_dadd_m(struct dt_d_s d, int n) { /* add N months to D */ if (UNLIKELY(!n)) { goto out; } switch (d.typ) { case DT_LDN: case DT_JDN: case DT_MDN: case DT_DAISY: /* daisy objects have no notion of months */ break; case DT_YMD: d.ymd = __ymd_add_m(d.ymd, n); break; case DT_YMCW: d.ymcw = __ymcw_add_m(d.ymcw, n); break; case DT_BIZDA: d.bizda = __bizda_add_m(d.bizda, n); break; case DT_YWD: /* ywd have no notion of months */ break; case DT_YD: /* yd have no notion of months */ break; case DT_DUNK: default: d.typ = DT_DUNK; d.u = 0; break; } out: return d; } DEFUN struct dt_d_s dt_dadd_y(struct dt_d_s d, int n) { /* add N years to D */ if (UNLIKELY(!n)) { /* cacn't use short-cut return here, it'd upset the IPO/LTO */ goto out; } switch (d.typ) { case DT_LDN: case DT_JDN: case DT_MDN: case DT_DAISY: /* daisy objects have no notion of years */ break; case DT_YMD: d.ymd = __ymd_add_y(d.ymd, n); break; case DT_YMCW: d.ymcw = __ymcw_add_y(d.ymcw, n); break; case DT_BIZDA: d.bizda = __bizda_add_y(d.bizda, n); break; case DT_YWD: d.ywd = __ywd_add_y(d.ywd, n); break; case DT_YD: d.yd = __yd_add_y(d.yd, n); break; case DT_DUNK: default: d.typ = DT_DUNK; d.u = 0; break; } out: return d; } DEFUN struct dt_d_s dt_dadd(struct dt_d_s d, struct dt_ddur_s dur) { if (UNLIKELY(!dur.dv)) { /* cacn't use short-cut return here, it'd upset the IPO/LTO */ goto out; } switch (dur.durtyp) { case DT_DURD: d = dt_dadd_d(d, dur.dv); break; case DT_DURBD: d = dt_dadd_b(d, dur.dv); break; case DT_DURWK: d = dt_dadd_w(d, dur.dv); break; case DT_DURMO: d = dt_dadd_m(d, dur.dv); break; case DT_DURYR: d = dt_dadd_y(d, dur.dv); break; default: case DT_DURUNK: /* huh? */ break; } out: return d; } DEFUN struct dt_ddur_s dt_neg_dur(struct dt_ddur_s dur) { dur.neg = (uint16_t)(~dur.neg & 0x01); switch (dur.durtyp) { case DT_DURD: case DT_DURBD: case DT_DURWK: case DT_DURMO: case DT_DURQU: case DT_DURYR: dur.dv = -dur.dv; break; default: break; } return dur; } DEFUN int dt_dur_neg_p(struct dt_ddur_s dur) { switch (dur.durtyp) { case DT_DURD: case DT_DURBD: case DT_DURWK: case DT_DURMO: case DT_DURQU: case DT_DURYR: return dur.dv < 0; default: break; } return dur.neg; } DEFUN struct dt_ddur_s dt_ddiff(dt_durtyp_t tgttyp, struct dt_d_s d1, struct dt_d_s d2) { struct dt_ddur_s res = dt_make_ddur(DT_DURUNK, 0); switch (tgttyp) { case DT_DURD: case DT_DURBD: { dt_daisy_t tmp1 = dt_conv_to_daisy(d1); dt_daisy_t tmp2 = dt_conv_to_daisy(d2); res = __daisy_diff(tmp1, tmp2); /* fix up result in case it's bizsi, i.e. kick weekends */ if (tgttyp == DT_DURBD) { dt_dow_t wdb = __daisy_get_wday(tmp2); res.dv = __get_nbdays(res.dv, wdb); } break; } case DT_DURYMD: { dt_ymd_t tmp1 = dt_conv_to_ymd(d1); dt_ymd_t tmp2 = dt_conv_to_ymd(d2); res = __ymd_diff(tmp1, tmp2); break; } case DT_DURYMCW: { dt_ymcw_t tmp1 = dt_conv_to_ymcw(d1); dt_ymcw_t tmp2 = dt_conv_to_ymcw(d2); res = __ymcw_diff(tmp1, tmp2); break; } case DT_DURYD: { dt_yd_t tmp1 = dt_conv_to_yd(d1); dt_yd_t tmp2 = dt_conv_to_yd(d2); res = __yd_diff(tmp1, tmp2); break; } case DT_DURYWD: { dt_ywd_t tmp1 = dt_conv_to_ywd(d1); dt_ywd_t tmp2 = dt_conv_to_ywd(d2); res = __ywd_diff(tmp1, tmp2); break; } case DT_DURBIZDA: case DT_DURUNK: default: break; } return res; } DEFUN int dt_dcmp(struct dt_d_s d1, struct dt_d_s d2) { /* for the moment D1 and D2 have to be of the same type. */ if (UNLIKELY(d1.typ != d2.typ)) { /* always the left one */ return -2; } switch (d1.typ) { case DT_DUNK: default: return -2; case DT_YMD: case DT_DAISY: case DT_BIZDA: case DT_YWD: case DT_YD: /* use arithmetic comparison */ if (d1.u == d2.u) { return 0; } else if (d1.u < d2.u) { return -1; } else /*if (d1.u > d2.u)*/ { return 1; } case DT_YMCW: /* use designated thing since ymcw dates aren't * increasing */ return __ymcw_cmp(d1.ymcw, d2.ymcw); } } DEFUN int dt_d_in_range_p(struct dt_d_s d, struct dt_d_s d1, struct dt_d_s d2) { /* use the following multiplication table * * |d,d2|v |d,d1|> -2 -1 0 1 * -2 -1 -1 -1 -1 * -1 -1 0 1 1 * 0 -1 0 1 1 * 1 -1 0 0 0 * * encoded in a 32bit uint */ static const uint32_t m = 0b10010111100101111010101111111111U; const unsigned int i = (dt_dcmp(d, d1) + 2) & 0b11U; const unsigned int j = (dt_dcmp(d, d2) + 2) & 0b11U; return 2 - ((m >> (i * 8U + j * 2U)) & 0b11U); } DEFUN __attribute__((pure)) struct dt_d_s dt_dfixup(struct dt_d_s d) { switch (d.typ) { case DT_YMD: d.ymd = __ymd_fixup(d.ymd); break; case DT_YMCW: d.ymcw = __ymcw_fixup(d.ymcw); break; case DT_YWD: d.ywd = __ywd_fixup(d.ywd); break; case DT_YD: d.yd = __yd_fixup(d.yd); break; case DT_BIZDA: d.bizda = __bizda_fixup(d.bizda); break; /* these can't be buggered */ case DT_DAISY: case DT_JDN: case DT_LDN: case DT_MDN: default: break; } return d; } #endif /* INCLUDED_date_core_c_ */ /* date-core.c ends here */ dateutils-0.4.5/lib/date-core.h000066400000000000000000000356201335042257000163070ustar00rootroot00000000000000/*** date-core.h -- our universe of dates * * Copyright (C) 2011-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of dateutils. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * **/ #if !defined INCLUDED_date_core_h_ #define INCLUDED_date_core_h_ #include #include #include #include #include "boops.h" #include "token.h" #if defined __cplusplus extern "C" { #endif /* __cplusplus */ /** * Date types we support. * Must not be more than 16. */ typedef enum { DT_DUNK, DT_YMD, DT_YMCW, DT_BIZDA, DT_YWD, DT_YD, DT_DAISY, DT_BIZSI, DT_JDN, DT_LDN, DT_MDN, DT_NDTYP, } dt_dtyp_t; /** * Duration types we support. * Must not be more than 16. */ typedef enum { DT_DURUNK, /* compacted durations */ DT_DURYMD, DT_DURYMCW, DT_DURBIZDA, DT_DURYWD, DT_DURYD, /* value-unit designated durations */ DT_DURD, DT_DURBD, DT_DURWK, DT_DURMO, DT_DURQU, DT_DURYR, DT_NDURTYP, } dt_durtyp_t; #if defined WITH_FAST_ARITH # define DT_MIN_YEAR (1917) # define DT_MAX_YEAR (2099) #else # define DT_MIN_YEAR (1601) # define DT_MAX_YEAR (4095) #endif /* WITH_FAST_ARITH */ /** ymds * ymds are just bcd coded concatenations of 8601 dates */ typedef union { uint32_t u; struct { #if BYTE_ORDER == BIG_ENDIAN /* 11 bits left */ unsigned int:11; unsigned int y:12; unsigned int m:4; unsigned int d:5; #elif BYTE_ORDER == LITTLE_ENDIAN unsigned int d:5; unsigned int m:4; unsigned int y:12; /* 11 bits left */ unsigned int:11; #else # warning unknown byte order #endif /* BYTE_ORDER */ }; } dt_ymd_t; /** ymcws * ymcws are year-month-count-weekday bcd coded. */ typedef union { uint32_t u; struct { #if BYTE_ORDER == BIG_ENDIAN /* 10 bits left */ unsigned int:10; unsigned int y:12; unsigned int m:4; unsigned int c:3; unsigned int w:3; #elif BYTE_ORDER == LITTLE_ENDIAN unsigned int w:3; unsigned int c:3; unsigned int m:4; unsigned int y:12; /* 10 bits left */ unsigned int:10; #else # warning unknown byte order #endif /* BYTE_ORDER */ }; } dt_ymcw_t; /** ywds * ywds are ISO 8601's year-week-day calendars. * By coincidence ycw's y and w slots are accessible through the ymcw bit field, * whether that's useful or not will occur to us later and then we might change * the layout. * Also, there's one auxiliary parameter the number of overhanging days * before the first day (Mon) in the first week, this number is in the * range of -3 to 3. For a year to start on Sunday it's +1, for a year * to start on Tuesday it's -1. */ typedef union { uint32_t u; struct { #define YWD_SUNWK_CNT (0) #define YWD_MONWK_CNT (1) #define YWD_ISOWK_CNT (2) #define YWD_ABSWK_CNT (3) #if BYTE_ORDER == BIG_ENDIAN /* 8 bits left */ unsigned int:7; unsigned int y:12; unsigned int c:7; unsigned int w:3; signed int hang:3; #elif BYTE_ORDER == LITTLE_ENDIAN signed int hang:3; unsigned int w:3; unsigned int c:7; unsigned int y:12; /* 8 bits left */ unsigned int:7; #else # warning unknown byte order #endif /* BYTE_ORDER */ }; } dt_ywd_t; typedef union { uint16_t u; uint32_t bs:16; struct { /* counting convention */ unsigned int cc:2; unsigned int:14; }; } __attribute__((__packed__)) dt_ywd_param_t; /** yds * yds are pure helpers and don't exist in the wild. */ typedef union { uint32_t u; struct { #if BYTE_ORDER == BIG_ENDIAN unsigned int y:16U; signed int d:16U; #elif BYTE_ORDER == LITTLE_ENDIAN signed int d:16U; unsigned int y:16U; #else # warning unknown byte order #endif /* BYTE_ORDER */ }; } dt_yd_t; /** daysi * daisys are days since X, -01-00 here */ typedef uint32_t dt_daisy_t; #define DT_DAISY_BASE_YEAR (DT_MIN_YEAR) /* and a signed version */ typedef int32_t dt_sdaisy_t; /** jdn (julian day number) * julian days are whole solar days since noon 1 Jan 4713 BC. * We will mostly use the daisy type for this. */ typedef float dt_jdn_t; /** ldn (lilian day number) * lilian days are whole solar days since the inception of the Gregorian * calendar, i.e. 15 Oct 1582. * We will mostly use the daisy type for this. */ typedef dt_daisy_t dt_ldn_t; /** mdn (matlab day number) * matlab days are whole proleptic solar days since 01 Jan 0. * We will mostly use the daisy type for this. */ typedef dt_daisy_t dt_mdn_t; /** bizda * bizdas is a calendar that counts business days before or after a * certain day in the month, mostly ultimo. */ typedef union { uint32_t u; struct { #define BIZDA_AFTER (0U)/*>*/ #define BIZDA_BEFORE (1U)/*<*/ #define BIZDA_ULTIMO (0U) #if BYTE_ORDER == BIG_ENDIAN /* 5 bits left */ unsigned int:5; /* business day */ unsigned int y:12; unsigned int m:4; unsigned int bd:5; #elif BYTE_ORDER == LITTLE_ENDIAN /* business day */ unsigned int bd:5; unsigned int m:4; unsigned int y:12; /* 5 bits left */ unsigned int:5; #else # warning unknown byte order #endif /* BYTE_ORDER */ }; } dt_bizda_t; typedef union { uint16_t u; uint32_t bs:16; struct { /* before or after */ unsigned int ab:1; /* reference day, use 00 for ultimo */ unsigned int ref:5; unsigned int:10; }; } __attribute__((__packed__)) dt_bizda_param_t; /** * Duration type. */ typedef int32_t dt_dur_t; /** * Collection of all date types. */ struct dt_d_s { /* date type */ dt_dtyp_t typ:4; /* unused here, but used by inherited types (e.g. dt_dt_s) */ uint32_t:3; /* error indicator, usually means date has been fixed up */ uint32_t fix:1; /* was duration predicate */ uint32_t xxx:1; /* negated predicate */ uint32_t neg:1; /* fill up to next ui16 boundary */ uint32_t:6; /* for parametrised types */ uint32_t param:16; union { uint32_t u; dt_ymd_t ymd; dt_ymcw_t ymcw; dt_ywd_t ywd; dt_daisy_t daisy; dt_daisy_t bizsi; dt_jdn_t jdn; dt_ldn_t ldn; dt_mdn_t mdn; /* all bizdas mixed into this */ dt_bizda_t bizda; /* for helper purposes only */ dt_yd_t yd; }; }; struct dt_ddur_s { /* date duration type */ dt_durtyp_t durtyp:4; /* unused here, but used by dt_dtdur_s */ uint32_t:3; /* error indicator, usually means date has been fixed up */ uint32_t fix:1; /* co-class indicator */ uint32_t cocl:1; /* negated predicate */ uint32_t neg:1; /* fill up to next ui16 boundary */ uint32_t:6; /* for parametrised types */ uint32_t param:16; union { uint32_t u; dt_ymd_t ymd; dt_ymcw_t ymcw; dt_ywd_t ywd; /* all bizdas mixed into this */ dt_bizda_t bizda; /* duration value, for value+unit durations only, * the .durtyp slot indicates the unit */ dt_dur_t dv; /* for helper purposes only */ dt_yd_t yd; }; }; /* widely understood notion of weekdays */ typedef enum { DT_MIRACLEDAY, DT_MONDAY, DT_TUESDAY, DT_WEDNESDAY, DT_THURSDAY, DT_FRIDAY, DT_SATURDAY, DT_SUNDAY, } dt_dow_t; /* match operations */ typedef uint32_t/*:3*/ oper_t; enum { OP_UNK = 0, OP_FALSE = OP_UNK, /* bit 1 set */ OP_EQ, /* bit 2 set */ OP_LT, OP_LE, /* bit 3 set */ OP_GT, OP_GE, /* bits 2 and 3 set */ OP_NE, /* bits 1, 2 and 3 set */ OP_TRUE, }; /* constants (for known calendars) */ #define GREG_DAYS_P_WEEK (7U) #define GREG_MONTHS_P_YEAR (12U) #define DUWW_BDAYS_P_WEEK (5U) /* decls */ /** * Like strptime() for our dates. * The format characters are _NOT_ compatible with strptime(). * If FMT is NULL the standard format for each calendric system is used, * see format.texi or dateutils info page. * * FMT can also be the name of a calendar: * - ymd for YMD dates * - ymcw for YMCW dates * - bizda for bizda/YMDU dates * * If optional EP is non-NULL it will point to the end of the parsed * date string. */ extern struct dt_d_s dt_strpd(const char *str, const char *fmt, char **ep); /** * Like strftime() for our dates */ extern size_t dt_strfd(char *restrict buf, size_t bsz, const char *fmt, struct dt_d_s); /** * Parse durations as in 1w5d, etc. */ extern struct dt_ddur_s dt_strpddur(const char *str, char **ep); /** * Print a duration. */ extern size_t dt_strfddur(char *restrict buf, size_t bsz, const char *fmt, struct dt_ddur_s); /** * Like time() but return the current date in the desired format. */ extern struct dt_d_s dt_date(dt_dtyp_t outtyp); /** * Convert D to another calendric system, specified by TGTTYP. */ extern struct dt_d_s dt_dconv(dt_dtyp_t tgttyp, struct dt_d_s); /** * Get the year count (gregorian) of a date, * calendars without the notion of a year will return 0. */ extern int dt_get_year(struct dt_d_s); /** * Get the month within the year of a date, * calendars without the notion of a month will return 0. */ extern int dt_get_mon(struct dt_d_s); /** * Get the weekday of a date. */ extern dt_dow_t dt_get_wday(struct dt_d_s); /** * Get the day of the month of a date. */ extern int dt_get_mday(struct dt_d_s d); /** * Get the business day count of a date in a month. */ extern int dt_get_bday(struct dt_d_s d); /** * Get the business day count of a date in a month Before/After REF. */ extern int dt_get_bday_q(struct dt_d_s d, dt_bizda_param_t bp); /** * Get the quarter number of a date. */ extern int dt_get_quarter(struct dt_d_s d); /** * Get the day of the year of a date. * This might only be intuitive for YMD dates. The formal definition * is to find a representation of D that lacks the notion of a month, * so for YMD dates this would be the sum of the days in the months * preceding M and the current day of the month in M. * For YMCW dates this will yield the n-th W-day in Y. * For calendars without the notion of a year this will return 0. */ extern unsigned int dt_get_yday(struct dt_d_s d); /** * Return N where N is the week within the year that THIS is in. */ extern int dt_get_wcnt_year(struct dt_d_s this, unsigned int wkcnt_convention); /** * Return N where N is the week within the month that THIS is in. */ extern int dt_get_wcnt_mon(struct dt_d_s this); /* converters */ extern dt_daisy_t dt_conv_to_daisy(struct dt_d_s); extern dt_ymd_t __daisy_to_ymd(dt_daisy_t); /* adders */ /** * Add duration DUR to date D. */ extern struct dt_d_s dt_dadd(struct dt_d_s d, struct dt_ddur_s dur); /** * Add N (gregorian) days to date D. */ extern struct dt_d_s dt_dadd_d(struct dt_d_s d, int n); /** * Add N business days to date D. */ extern struct dt_d_s dt_dadd_b(struct dt_d_s d, int n); /** * Add N weeks to date D. */ extern struct dt_d_s dt_dadd_w(struct dt_d_s d, int n); /** * Add N months to date D. * For calendars without the notion of months the result is D. */ extern struct dt_d_s dt_dadd_m(struct dt_d_s d, int n); /** * Add N years to date D. * For calendars without the notion of years the result is D. */ extern struct dt_d_s dt_dadd_y(struct dt_d_s d, int n); /** * Negate the duration. */ extern struct dt_ddur_s dt_neg_dur(struct dt_ddur_s); /** * Is duration DUR negative? */ extern int dt_dur_neg_p(struct dt_ddur_s dur); /** * Get duration between D1 and D2. * The result will be of type TGTTYP, * the calendar of D1 will be used, e.g. its month-per-year, days-per-week, * etc. conventions count. * If instead D2 should count, swap D1 and D2 and negate the duration * by setting/clearing the neg bit. */ extern struct dt_ddur_s dt_ddiff(dt_durtyp_t tgttyp, struct dt_d_s d1, struct dt_d_s d2); /** * Compare two dates, yielding 0 if they are equal, -1 if D1 is older, * 1 if D1 is younger than the D2. */ extern int dt_dcmp(struct dt_d_s d1, struct dt_d_s d2); /** * Check if D is in the interval spanned by D1 and D2, * 1 if D1 is younger than the D2. */ extern int dt_d_in_range_p(struct dt_d_s d, struct dt_d_s d1, struct dt_d_s d2); #if defined LIBDUT /** * Return the base date/time as struct dt_d_s. * Defined in dt-core.c */ extern struct dt_d_s dt_get_dbase(void); #endif /* LIBDUT */ /** * Crop dates with days beyond ultimo. */ extern __attribute__((pure)) struct dt_d_s dt_dfixup(struct dt_d_s); /* some useful gimmicks, sort of */ static inline __attribute__((pure, const)) struct dt_d_s dt_d_initialiser(void) { #if defined HAVE_SLOPPY_STRUCTS_INIT static const struct dt_d_s res = {}; #else /* HAVE_SLOPPY_STRUCTS_INIT */ static const struct dt_d_s res; #endif /* HAVE_SLOPPY_STRUCTS_INIT */ return res; } /* other ctors */ static inline struct dt_d_s dt_make_ymd(unsigned int y, unsigned int m, unsigned int d) { struct dt_d_s res; res.typ = DT_YMD; res.neg = 0U; res.fix = 0U; res.param = 0U; res.ymd.y = y; res.ymd.m = m; res.ymd.d = d; return res; } static inline struct dt_d_s dt_make_ymcw(unsigned int y, unsigned int m, unsigned int c, unsigned int w) { struct dt_d_s res; res.typ = DT_YMCW; res.neg = 0U; res.fix = 0U; res.param = 0U; res.ymcw.y = y; res.ymcw.m = m; res.ymcw.c = c; res.ymcw.w = w; return res; } static inline struct dt_ddur_s dt_make_ddur(dt_durtyp_t typ, dt_dur_t d) { #if defined HAVE_ANON_STRUCTS_INIT return (struct dt_ddur_s){typ, .dv = d}; #else struct dt_ddur_s res = {typ}; res.dv = d; return res; #endif } static inline dt_bizda_param_t __get_bizda_param(struct dt_d_s that) { dt_bizda_param_t p; p.bs = that.param; return p; } static inline dt_bizda_param_t __make_bizda_param(unsigned int ab, unsigned int ref) { dt_bizda_param_t p; p.ab = ab; p.ref = ref; return p; } static inline dt_ywd_param_t __get_ywd_param(struct dt_d_s that) { return (dt_ywd_param_t){.bs = that.param}; } static inline dt_ywd_param_t __make_ywd_param(unsigned int cc) { dt_ywd_param_t p; p.cc = cc; return p; } static inline bool __leapp(unsigned int y) { #if defined WITH_FAST_ARITH return y % 4 == 0; #else /* !WITH_FAST_ARITH */ return y % 4 == 0 && (y % 100 != 0 || y % 400 == 0); #endif /* WITH_FAST_ARITH */ } #if defined __cplusplus } #endif /* __cplusplus */ #endif /* INCLUDED_date_core_h_ */ dateutils-0.4.5/lib/dt-core-private.h000066400000000000000000000036671335042257000174570ustar00rootroot00000000000000/*** dt-core-private.h -- our universe of datetimes, private bits * * Copyright (C) 2012-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of dateutils. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * **/ /* private portion of dt-core.h */ #if !defined INCLUDED_dt_core_private_h_ #define INCLUDED_dt_core_private_h_ #include "dt-core.h" extern dt_dttyp_t __trans_dtfmt(const char **fmt); extern dt_dtdurtyp_t __trans_dtdurfmt(const char**fmt); #endif /* INCLUDED_dt_core_private_h_ */ dateutils-0.4.5/lib/dt-core-strpf.c000066400000000000000000000255201335042257000171260ustar00rootroot00000000000000/*** dt-core-strpf.c -- parser and formatter funs for dt-core * * Copyright (C) 2011-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of dateutils. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * **/ /* implementation part of date-core-strpf.h */ #if !defined INCLUDED_dt_core_strpf_c_ #define INCLUDED_dt_core_strpf_c_ #if defined HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include "strops.h" #include "token.h" #include "dt-core.h" #include "dt-core-strpf.h" #if defined __INTEL_COMPILER /* we MUST return a char* */ # pragma warning (disable:2203) #elif defined __GNUC__ # pragma GCC diagnostic ignored "-Wcast-qual" #endif /* __INTEL_COMPILER */ #if !defined DEFUN # define DEFUN #endif /* !DEFUN */ #if defined SKIP_LEAP_ARITH # undef WITH_LEAP_SECONDS #endif /* SKIP_LEAP_ARITH */ static int32_t try_zone(const char *str, const char **ep) { int minusp = 0; const char *sp = str; int32_t res = 0; switch (*sp) { int32_t tmp; const char *tp; const char *up; case '-': minusp = 1; case '+': /* read hour part */ if ((tmp = strtoi_lim(sp + 1U, &tp, 0, 14)) < 0) { break; } else if (tp - sp < 3U) { /* only accept fully zero-padded hours */ break; } res += 3600 * tmp; /* colon separator is optional */ if (*tp == ':') { tp++; } /* read minute part */ if ((tmp = strtoi_lim(tp, &up, 0, 59)) < 0) { break; } else if (up - tp < 2U) { /* only accept zero-padded minutes */ break; } else { tp = up; } res += 60 * tmp; /* at least we've got hours and minutes */ sp = tp; /* again colon separator is optional */ if (*tp == ':') { tp++; } /* read second part */ if ((tmp = strtoi_lim(tp, &tp, 0, 59)) < 0) { break; } res += tmp; /* fully determined */ sp = tp; break; case 'Z': /* accept Zulu specifier */ sp++; break; default: /* clearly a mistake to advance SP */ break; } /* res.typ coincides with DT_SANDWICH_D_ONLY() if we jumped here */ if (ep != NULL) { *ep = sp; } return minusp ? -res : res; } static struct dt_dt_s __fixup_zdiff(struct dt_dt_s dt, int32_t zdiff) { /* apply time zone difference */ /* reuse dt for result */ #if defined HAVE_ANON_STRUCTS_INIT dt = dt_dtadd(dt, (struct dt_dtdur_s){DT_DURS, .dv = -zdiff}); #else { struct dt_dtdur_s tmp = {DT_DURS}; tmp.dv = -zdiff; dt = dt_dtadd(dt, tmp); } #endif dt.znfxd = 1; return dt; } DEFUN struct dt_dt_s __strpdt_std(const char *str, char **ep) { /* code dupe, see __strpd_std() */ struct dt_dt_s res = dt_dt_initialiser(); struct strpdt_s d = strpdt_initialiser(); const char *sp; if ((sp = str) == NULL) { goto out; } /* check for epoch notation */ if (*sp == '@') { /* yay, epoch */ const char *tmp; d.i = strtoi(++sp, &tmp); if (UNLIKELY(d.i == -1 && sp == tmp)) { sp--; } else { /* let's make a DT_SEXY */ res.typ = DT_SEXY; res.sxepoch = d.i; } goto out; } with (char *tmp) { /* let date-core do the hard yakka */ if ((res.d = __strpd_std(str, &tmp)).typ == DT_DUNK) { /* not much use parsing on */ goto try_time; } sp = tmp; } /* check for the d/t separator */ switch (*sp) { case 'T': case ' ': case '\t': /* could be a time, could be something, else * make sure we leave a mark */ str = sp++; break; default: /* should be a no-op */ dt_make_d_only(&res, res.d.typ); goto out; } try_time: /* and now parse the time */ if ((d.st.h = strtoi_lim(sp, &sp, 0, 24)) < 0 || *sp != ':') { sp = str; goto out; } else if ((sp++, d.st.m = strtoi_lim(sp, &sp, 0, 59)) < 0) { d.st.m = 0; goto out; } else if (*sp != ':') { goto eval_time; } else if ((sp++, d.st.s = strtoi_lim(sp, &sp, 0, 60)) < 0) { d.st.s = 0; } else if (*sp != '.') { goto eval_time; } else if ((sp++, d.st.ns = strtoi_lim(sp, &sp, 0, 999999999)) < 0) { d.st.ns = 0; goto eval_time; } eval_time: if (UNLIKELY(d.st.h == 24)) { if (d.st.m || d.st.s || d.st.ns) { sp = str; goto out; } } res.t.hms.h = d.st.h; res.t.hms.m = d.st.m; res.t.hms.s = d.st.s; if (res.d.typ > DT_DUNK) { const char *tp; dt_make_sandwich(&res, res.d.typ, DT_HMS); /* check for the zone stuff */ if ((d.zdiff = try_zone(sp, &tp))) { res = __fixup_zdiff(res, d.zdiff); } else if (tp > sp) { res.znfxd = 1U; } sp = tp; } else { dt_make_t_only(&res, DT_HMS); } out: /* res.typ coincides with DT_SANDWICH_D_ONLY() if we jumped here */ if (ep != NULL) { *ep = (char*)sp; } return res; } DEFUN int __strpdt_card(struct strpdt_s *d, const char *sp, struct dt_spec_s s, char **ep) { int res = 0; switch (s.spfl) { default: case DT_SPFL_UNK: res = -1; break; case DT_SPFL_N_DSTD: case DT_SPFL_N_YEAR: case DT_SPFL_N_MON: case DT_SPFL_N_DCNT_MON: case DT_SPFL_N_DCNT_WEEK: case DT_SPFL_N_DCNT_YEAR: case DT_SPFL_N_WCNT_MON: case DT_SPFL_N_WCNT_YEAR: case DT_SPFL_S_WDAY: case DT_SPFL_S_MON: case DT_SPFL_S_QTR: case DT_SPFL_N_QTR: res = __strpd_card(&d->sd, sp, s, ep); goto out_direct; case DT_SPFL_N_TSTD: case DT_SPFL_N_HOUR: case DT_SPFL_N_MIN: case DT_SPFL_N_SEC: case DT_SPFL_N_NANO: case DT_SPFL_S_AMPM: res = __strpt_card(&d->st, sp, s, ep); goto out_direct; case DT_SPFL_N_EPOCH: { /* read over @ */ const char *tp = sp; tp += *tp == '@'; d->i = strtoi(tp, &tp); if (UNLIKELY(d->i < 0 || tp == sp)) { res = -1; } else { sp = tp; } break; } case DT_SPFL_N_ZDIFF: { const char *tp; if ((d->zdiff = try_zone(sp, &tp)) || tp > sp) { d->zngvn = 1; } sp = tp; break; } case DT_SPFL_LIT_PERCENT: if (*sp++ != '%') { res = -1; } break; case DT_SPFL_LIT_TAB: if (*sp++ != '\t') { res = -1; } break; case DT_SPFL_LIT_NL: if (*sp++ != '\n') { res = -1; } break; } /* assign end pointer */ if (ep != NULL) { *ep = (char*)sp; } out_direct: return res; } DEFUN size_t __strfdt_card( char *buf, size_t bsz, struct dt_spec_s s, struct strpdt_s *d, struct dt_dt_s that) { size_t res = 0; switch (s.spfl) { default: case DT_SPFL_UNK: break; case DT_SPFL_N_DSTD: case DT_SPFL_N_YEAR: case DT_SPFL_N_MON: case DT_SPFL_N_DCNT_WEEK: case DT_SPFL_N_DCNT_MON: case DT_SPFL_N_DCNT_YEAR: case DT_SPFL_N_WCNT_MON: case DT_SPFL_N_WCNT_YEAR: case DT_SPFL_S_WDAY: case DT_SPFL_S_MON: case DT_SPFL_S_QTR: case DT_SPFL_N_QTR: res = __strfd_card(buf, bsz, s, &d->sd, that.d); break; case DT_SPFL_N_TSTD: case DT_SPFL_N_HOUR: case DT_SPFL_N_MIN: case DT_SPFL_N_SEC: case DT_SPFL_S_AMPM: case DT_SPFL_N_NANO: res = __strft_card(buf, bsz, s, &d->st, that.t); break; case DT_SPFL_N_EPOCH: { /* convert to sexy */ int64_t sexy = dt_conv_to_sexy(that).sexy; res = snprintf(buf, bsz, "%" PRIi64, sexy); break; } case DT_SPFL_N_ZDIFF: { int32_t z = d->zdiff; char sign = '+'; if (z < 0) { z = -z; sign = '-'; } res = snprintf( buf, bsz, "%c%02u:%02u", sign, (uint32_t)z / 3600U, ((uint32_t)z / 60U) % 60U); break; } case DT_SPFL_LIT_PERCENT: /* literal % */ buf[res++] = '%'; break; case DT_SPFL_LIT_TAB: /* literal tab */ buf[res++] = '\t'; break; case DT_SPFL_LIT_NL: /* literal \n */ buf[res++] = '\n'; break; } return res; } DEFUN size_t __strfdt_dur( char *buf, size_t bsz, struct dt_spec_s s, struct strpdt_s *d, struct dt_dtdur_s that) { switch (s.spfl) { default: case DT_SPFL_UNK: return 0; case DT_SPFL_N_DSTD: case DT_SPFL_N_YEAR: case DT_SPFL_N_MON: case DT_SPFL_N_DCNT_WEEK: case DT_SPFL_N_DCNT_MON: case DT_SPFL_N_DCNT_YEAR: case DT_SPFL_N_WCNT_MON: case DT_SPFL_N_WCNT_YEAR: case DT_SPFL_S_WDAY: case DT_SPFL_S_MON: case DT_SPFL_S_QTR: case DT_SPFL_N_QTR: return __strfd_dur(buf, bsz, s, &d->sd, that.d); /* noone's ever bothered doing the same thing for times */ case DT_SPFL_N_TSTD: case DT_SPFL_N_SEC:; int64_t dv; dv = that.dv; switch (that.durtyp) { default: if (that.d.durtyp != DT_DURD) { return 0U; } dv = (int64_t)that.d.dv * HOURS_PER_DAY; /*@fallthrough@*/ case DT_DURH: dv *= MINS_PER_HOUR; /*@fallthrough@*/ case DT_DURM: dv *= SECS_PER_MIN; /*@fallthrough@*/ case DT_DURS: if (LIKELY(!that.tai)) { return (size_t)snprintf( buf, bsz, "%" PRIi64 "s", dv); } else { return (size_t)snprintf( buf, bsz, "%" PRIi64 "rs", dv); } break; } break; case DT_SPFL_N_NANO: { int64_t dur = that.dv; switch (that.durtyp) { case DT_DURS: dur *= NANOS_PER_SEC; /*@fallthrough@*/ case DT_DURNANO: if (LIKELY(!that.tai)) { return (size_t)snprintf( buf, bsz, "%" PRIi64 "ns", dur); } else { return (size_t)snprintf( buf, bsz, "%" PRIi64 "rns", dur); } default: break; } break; } case DT_SPFL_LIT_PERCENT: /* literal % */ *buf = '%'; break; case DT_SPFL_LIT_TAB: /* literal tab */ *buf = '\t'; break; case DT_SPFL_LIT_NL: /* literal \n */ *buf = '\n'; break; } return 1; } static size_t __strfdt_xdn(char *buf, size_t bsz, struct dt_dt_s that) { double dn; switch (that.d.typ) { case DT_JDN: dn = (double)that.d.jdn; break; case DT_LDN: dn = (double)that.d.ldn; if (dt_sandwich_only_d_p(that)) { return snprintf(buf, bsz, "%.0f", dn); } break; case DT_MDN: dn = (double)that.d.mdn; if (dt_sandwich_only_d_p(that)) { return snprintf(buf, bsz, "%.0f", dn); } break; default: return 0; } if (dt_sandwich_p(that)) { unsigned int ss = __secs_since_midnight(that.t); dn += (double)ss / (double)SECS_PER_DAY; } return snprintf(buf, bsz, "%.6f", dn); } #endif /* INCLUDED_dt_core_strpf_c_ */ dateutils-0.4.5/lib/dt-core-strpf.h000066400000000000000000000053211335042257000171300ustar00rootroot00000000000000/*** dt-core-strpf.h -- parser and formatter funs for dt-core * * Copyright (C) 2011-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of dateutils. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * **/ #if !defined INCLUDED_dt_core_strpf_h_ #define INCLUDED_dt_core_strpf_h_ #if defined __cplusplus extern "C" { #endif /* __cplusplus */ /* helpers */ static inline __attribute__((pure, const)) struct strpdt_s strpdt_initialiser(void) { #if defined HAVE_SLOPPY_STRUCTS_INIT static const struct strpdt_s res = {}; #else static const struct strpdt_s res; #endif /* HAVE_SLOPPY_STRUCTS_INIT */ return res; } #if defined INCLUDED_dt_core_h_ /** * Parse STR with the standard parser, put the end of the parsed string in EP.*/ extern struct dt_dt_s __strpdt_std(const char *str, char **ep); #endif /* INCLUDED_dt_core_h_ */ /* self-explanatory funs, innit? */ extern int __strpdt_card(struct strpdt_s*, const char *sp, struct dt_spec_s s, char **ep); extern size_t __strfdt_card( char *buf, size_t bsz, struct dt_spec_s s, struct strpdt_s *d, struct dt_dt_s that); extern size_t __strfdt_dur( char *buf, size_t bsz, struct dt_spec_s s, struct strpdt_s *d, struct dt_dtdur_s that); #if defined __cplusplus } #endif /* __cplusplus */ #endif /* INCLUDED_dt_core_strpf_h_ */ dateutils-0.4.5/lib/dt-core-tz-glue.c000066400000000000000000000077461335042257000173710ustar00rootroot00000000000000/*** dt-core-tz-glue.c -- gluing date/times and tzs * * Copyright (C) 2012-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of dateutils. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * **/ /* dt-core-tz-glue.h implementation */ #if !defined INCLUDED_dt_core_tz_glue_c_ #define INCLUDED_dt_core_tz_glue_c_ #if defined HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include "nifty.h" #include "dt-core-tz-glue.h" #if !defined DEFUN # define DEFUN #endif /* !DEFUN */ /** * Return a dt object that forgot about DT's zone and uses ZONE instead. */ DEFUN struct dt_dt_s dtz_forgetz(struct dt_dt_s d, zif_t zone) { dt_ssexy_t d_unix; dt_ssexy_t d_locl; int32_t zdiff; if (dt_unk_p(d) || dt_sandwich_only_d_p(d)) { /* we need date/times to do the conversion */ return d; } else if (d.znfxd) { /* already forgotten about */ return d; } else if (zone == NULL) { /* convert from UTC, great idea */ return d; } /* convert date/time part to unix stamp */ d_locl = dt_to_unix_epoch(d); d_unix = zif_utc_time(zone, d_locl); if (LIKELY((zdiff = d_unix - d_locl))) { /* let dt_dtadd() do the magic */ #if defined HAVE_ANON_STRUCTS_INIT d = dt_dtadd(d, (struct dt_dtdur_s){DT_DURS, .dv = zdiff}); #else { struct dt_dtdur_s tmp = {DT_DURS}; tmp.dv = zdiff; d = dt_dtadd(d, tmp); } #endif d.znfxd = 1; if (zdiff > 0) { d.neg = 1; d.zdiff = (uint16_t)(zdiff / ZDIFF_RES); } else if (zdiff < 0) { d.zdiff = (uint16_t)(-zdiff / ZDIFF_RES); } } return d; } /** * Return a dt object from a UTC'd DT that uses ZONE. */ DEFUN struct dt_dt_s dtz_enrichz(struct dt_dt_s d, zif_t zone) { dt_ssexy_t d_unix; dt_ssexy_t d_locl; int32_t zdiff; if (dt_sandwich_only_d_p(d)) { /* nah, we need a date/time for this */ return d; } else if (zone == NULL) { /* UTC -> UTC? */ return d; } /* convert date/time part to unix stamp */ d_unix = dt_to_unix_epoch(d); d_locl = zif_local_time(zone, d_unix); if (LIKELY((zdiff = d_locl - d_unix))) { /* let dt_dtadd() do the magic */ #if defined HAVE_ANON_STRUCTS_INIT d = dt_dtadd(d, (struct dt_dtdur_s){DT_DURS, .dv = zdiff}); #else { struct dt_dtdur_s tmp = {DT_DURS}; tmp.dv = zdiff; d = dt_dtadd(d, tmp); } #endif if (zdiff > 0) { d.zdiff = (uint16_t)(zdiff / ZDIFF_RES); } else if (zdiff < 0) { d.neg = 1; d.zdiff = (uint16_t)(-zdiff / ZDIFF_RES); } } else { /* no difference to UTC means the offset is +00:00 */ d.zdiff = 0U; d.neg = 0U; } return d; } #endif /* INCLUDED_dt_core_tz_glue_c_ */ /* dt-core-tz-glue.c ends here */ dateutils-0.4.5/lib/dt-core-tz-glue.h000066400000000000000000000045671335042257000173740ustar00rootroot00000000000000/*** dt-core-tz-glue.h -- glue between tzraw and dt-core * * Copyright (C) 2012-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of dateutils. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * **/ #if !defined INCLUDED_dt_core_tz_glue_h_ #define INCLUDED_dt_core_tz_glue_h_ /* include the guys we need gluing, innit */ #include "dt-core.h" #include "tzraw.h" #if defined __cplusplus extern "C" { #endif /* __cplusplus */ /* decls */ /** * Return a dt object that forgot about DT's zone and uses ZONE instead. * In other words: convert from locally represented DT to UTC. */ extern struct dt_dt_s dtz_forgetz(struct dt_dt_s dt, zif_t zone); /** * Return a dt object from a UTC'd DT that uses ZONE. * In other words: convert from UTC represented DT to local ZONE time. */ extern struct dt_dt_s dtz_enrichz(struct dt_dt_s dt, zif_t zone); #if defined __cplusplus } #endif /* __cplusplus */ #endif /* INCLUDED_dt_core_tz_glue_h_ */ dateutils-0.4.5/lib/dt-core.c000066400000000000000000001155321335042257000157750ustar00rootroot00000000000000/*** dt-core.c -- our universe of datetimes * * Copyright (C) 2011-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of dateutils. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * **/ /* implementation part of dt-core.h */ #if !defined INCLUDED_dt_core_c_ #define INCLUDED_dt_core_c_ #if defined HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #include #include #include "date-core.h" #include "time-core.h" #include "strops.h" #include "leaps.h" #include "boops.h" #include "nifty.h" #include "dt-core.h" #include "dt-core-private.h" #include "date-core.h" #include "date-core-private.h" #include "time-core.h" #include "time-core-private.h" /* parsers and formatters */ #include "date-core-strpf.h" #include "time-core-strpf.h" #if defined SKIP_LEAP_ARITH # undef WITH_LEAP_SECONDS #endif /* SKIP_LEAP_ARITH */ #if defined WITH_LEAP_SECONDS # include "leap-seconds.h" #endif /* WITH_LEAP_SECONDS */ #if defined __INTEL_COMPILER /* we MUST return a char* */ # pragma warning (disable:2203) #elif defined __GNUC__ # pragma GCC diagnostic ignored "-Wcast-qual" #endif /* __INTEL_COMPILER */ #if !defined DEFUN # define DEFUN #endif /* !DEFUN */ struct strpdt_s { struct strpd_s sd; struct strpt_s st; long int i; /* use 31 bits for the difference */ int32_t zdiff:31; /* and 1 to indicate if it was specified */ int32_t zngvn:1; }; /* used for arithmetic */ struct strpdti_s { signed int m; signed int d; signed int w; signed int b; signed int S; }; /* converters and stuff */ #if !defined DT_DAISY_BASE_YEAR # error daisy base year cannot be obtained #elif DT_DAISY_BASE_YEAR == 1917 # define DAISY_UNIX_BASE (19359L) # define DAISY_GPS_BASE (23016L) #elif DT_DAISY_BASE_YEAR == 1753 # define DAISY_UNIX_BASE (79258L) # define DAISY_GPS_BASE (82915L) #elif DT_DAISY_BASE_YEAR == 1601 # define DAISY_UNIX_BASE (134775L) # define DAISY_GPS_BASE (138432L) #else # error unknown daisy base year #endif /* DT_DAISY_BASE_YEAR */ #if DAISY_GPS_BASE - DAISY_UNIX_BASE != 3657L # error daisy unix and gps bases diverge #endif /* static assert */ static inline dt_ssexy_t __to_unix_epoch(struct dt_dt_s dt) { /* daisy is competing with the prevalent unix epoch, this is the offset */ struct dt_d_s dd; dt_ssexy_t res; if (dt.typ == DT_SEXY) { /* no way to find out, is there */ return dt.sexy; } else if (dt_sandwich_p(dt) || dt_sandwich_only_d_p(dt)) { dd = dt.d; } else if (dt_sandwich_only_t_p(dt)) { dd = dt_get_base().d; } else { return 0; } res = (dt_conv_to_daisy(dd) - DAISY_UNIX_BASE) * SECS_PER_DAY; res += (dt.t.hms.h * 60 + dt.t.hms.m) * 60 + dt.t.hms.s; return res; } /* public version */ dt_ssexy_t dt_to_unix_epoch(struct dt_dt_s dt) { return __to_unix_epoch(dt); } static inline dt_ssexy_t __to_gps_epoch(struct dt_dt_s dt) { if (dt.typ == DT_SEXY) { /* no way to find out, is there */ return dt.sexy; } else if (dt_sandwich_p(dt) || dt_sandwich_only_d_p(dt)) { dt_daisy_t d = dt_conv_to_daisy(dt.d); dt_ssexy_t res = (d - DAISY_GPS_BASE) * SECS_PER_DAY; if (dt_sandwich_p(dt)) { res += (dt.t.hms.h * 60 + dt.t.hms.m) * 60 + dt.t.hms.s; } return res; } return 0; } /* public version */ dt_ssexy_t dt_to_gps_epoch(struct dt_dt_s dt) { return __to_gps_epoch(dt); } static inline struct dt_dt_s dt_conv_to_sexy(struct dt_dt_s dt) { if (dt.typ == DT_SEXY) { return dt; } else if (dt_sandwich_only_t_p(dt)) { dt.sxepoch = (dt.t.hms.h * 60 + dt.t.hms.m) * 60 + dt.t.hms.s; } else if (dt_sandwich_p(dt) || dt_sandwich_only_d_p(dt)) { dt.sxepoch = __to_unix_epoch(dt); } else { dt = dt_dt_initialiser(); } /* make sure we hand out sexies */ dt.typ = DT_SEXY; return dt; } static inline struct dt_dt_s __sexy_to_daisy(dt_ssexy_t sx) { struct dt_dt_s res = dt_dt_initialiser(); res.t.hms.s = sx % SECS_PER_MIN; sx /= SECS_PER_MIN; res.t.hms.m = sx % MINS_PER_HOUR; sx /= MINS_PER_HOUR; res.t.hms.h = sx % HOURS_PER_DAY; sx /= HOURS_PER_DAY; /* rest is a day-count, move to daisy */ res.d.daisy = sx + DAISY_UNIX_BASE; /* sandwichify */ dt_make_sandwich(&res, DT_DAISY, DT_HMS); return res; } static inline struct dt_dt_s __ymdhms_to_ymd(dt_ymdhms_t x) { struct dt_dt_s res = dt_dt_initialiser(); res.t.hms.s = x.S; res.t.hms.m = x.M; res.t.hms.h = x.H; /* rest is a day-count, move to daisy */ res.d.ymd.y = x.y; res.d.ymd.m = x.m; res.d.ymd.d = x.d; /* sandwichify */ dt_make_sandwich(&res, DT_YMD, DT_HMS); return res; } static inline __attribute__((unused)) struct dt_dt_s __epoch_to_ymd_sandwich(dt_ssexy_t sx) { struct dt_dt_s res; res.t.hms.s = sx % SECS_PER_MIN; sx /= SECS_PER_MIN; res.t.hms.m = sx % MINS_PER_HOUR; sx /= MINS_PER_HOUR; res.t.hms.h = sx % HOURS_PER_DAY; sx /= HOURS_PER_DAY; res.d.ymd = __daisy_to_ymd(sx + DAISY_UNIX_BASE); dt_make_sandwich(&res, DT_YMD, DT_HMS); return res; } static inline dt_sexy_t __sexy_add(dt_sexy_t sx, struct dt_dtdur_s dur) { /* sexy add * only works for continuous types (DAISY, etc.) * we need to take leap seconds into account here */ dt_ssexy_t dv = dur.dv; switch (dur.durtyp) { case DT_DURH: dv *= MINS_PER_HOUR; case DT_DURM: dv *= SECS_PER_MIN; case DT_DURS: break; case DT_DURNANO: dv /= NANOS_PER_SEC; break; case DT_DURD: case DT_DURBD: dv = (dt_ssexy_t)dur.d.dv * SECS_PER_DAY; /*@fallthrough@*/ case DT_DURUNK: dv += dur.t.sdur; default: break; } /* just go through with it */ return sx + dv; } #if defined WITH_LEAP_SECONDS && defined SKIP_LEAP_ARITH #error "bugger" #endif /* guessing parsers */ #include "token.h" #include "strops.h" #if defined WITH_LEAP_SECONDS && defined SKIP_LEAP_ARITH #error "bugger" #endif #include "dt-core-strpf.c" static const char ymdhms_dflt[] = "%FT%T"; static const char ymcwhms_dflt[] = "%Y-%m-%c-%wT%T"; static const char ywdhms_dflt[] = "%rY-W%V-%uT%T"; static const char ydhms_dflt[] = "%Y-%D"; static const char daisyhms_dflt[] = "%dT%T"; static const char sexy_dflt[] = "%s"; static const char bizsihms_dflt[] = "%dbT%T"; static const char bizdahms_dflt[] = "%Y-%m-%dbT%T"; static const char ymdhmsdur_dflt[] = "%0Y-%0m-%0dT%0H:%0M:%0S"; static const char ymcwhmsdur_dflt[] = "%Y-%0m-%0w-%0dT%0H:%0M:%0S"; static const char ywdhmsdur_dflt[] = "%rY-W%0w-%0dT%0H:%0M:%0S"; static const char ydhmsdur_dflt[] = "%Y-%0dT%0H:%0M:%0S"; static const char daisyhmsdur_dflt[] = "%dT%0H:%0M:%0S"; static const char sexydur_dflt[] = "%s"; static const char bizsihmsdur_dflt[] = "%dbT%0H:%0M:%0S"; static const char bizdahmsdur_dflt[] = "%Y-%0m-%0dbT%0H:%0M:%0S"; DEFUN dt_dttyp_t __trans_dtfmt(const char **fmt) { if (UNLIKELY(*fmt == NULL)) { /* um, great */ ; } else if (LIKELY(**fmt == '%')) { /* don't worry about it */ ; } else { const dt_dtyp_t tmp = __trans_dfmt_special(*fmt); /* thanks gcc for making me cast this :( */ switch ((unsigned int)tmp) { default: break; case DT_YMD: *fmt = ymdhms_dflt; break; case DT_YMCW: *fmt = ymcwhms_dflt; break; case DT_BIZDA: *fmt = bizdahms_dflt; break; case DT_DAISY: *fmt = daisyhms_dflt; break; case DT_SEXY: *fmt = sexy_dflt; break; case DT_BIZSI: *fmt = bizsihms_dflt; break; case DT_YWD: *fmt = ywdhms_dflt; break; case DT_YD: *fmt = ydhms_dflt; break; } return (dt_dttyp_t)tmp; } return (dt_dttyp_t)DT_DUNK; } DEFUN dt_dtdurtyp_t __trans_dtdurfmt(const char **fmt) { if (UNLIKELY(*fmt == NULL)) { /* um, great */ ; } else if (LIKELY(**fmt == '%')) { /* don't worry about it */ ; } else { unsigned int tmp = __trans_dfmt_special(*fmt); /* thanks gcc for making me cast this :( */ switch ((unsigned int)tmp) { default: break; case DT_YMD: *fmt = ymdhmsdur_dflt; tmp = DT_DURYMD; break; case DT_YMCW: *fmt = ymcwhmsdur_dflt; tmp = DT_DURYMCW; break; case DT_BIZDA: *fmt = bizdahmsdur_dflt; tmp = DT_DURBIZDA; break; case DT_DAISY: *fmt = daisyhmsdur_dflt; tmp = DT_DURD; break; case DT_SEXY: *fmt = sexydur_dflt; tmp = DT_DURS; break; case DT_BIZSI: *fmt = bizsihmsdur_dflt; tmp = DT_DURBD; break; case DT_YWD: *fmt = ywdhmsdur_dflt; tmp = DT_DURYWD; break; case DT_YD: *fmt = ydhmsdur_dflt; tmp = DT_DURYD; break; } return (dt_dtdurtyp_t)tmp; } return (dt_dtdurtyp_t)DT_DURUNK; } #define FFFF_GMTIME_SUBDAY #include "gmtime.h" static struct timeval now_tv(void) { /* singleton, gives a consistent `now' throughout the whole run */ static struct timeval tv; if (LIKELY(tv.tv_sec)) { /* perfect */ ; } else if (gettimeofday(&tv, NULL) < 0) { /* big cinema :( */ tv = (struct timeval){0U, 0U}; } return tv; } static struct tm now_tm(void) { /* singleton, gives a consistent `now' throughout the whole run */ static struct tm tm; struct timeval tv; if (LIKELY(tm.tm_year)) { /* sit back and relax */ ; } else if ((tv = now_tv()).tv_sec == 0U) { /* big cinema :( */ #if defined HAVE_SLOPPY_STRUCTS_INIT return (struct tm){}; #else /* !HAVE_SLOPPY_STRUCTS_INIT */ memset(&tm, 0, sizeof(tm)); #endif /* HAVE_SLOPPY_STRUCTS_INIT */ } else { ffff_gmtime(&tm, tv.tv_sec); } return tm; } static struct strpdt_s massage_strpdt(struct strpdt_s d) { /* the reason we do this separately is that we don't want to bother * the pieces of code that use the guesser for different reasons */ if (UNLIKELY(d.sd.y == 0U)) { #if defined HAVE_SLOPPY_STRUCTS_INIT static const struct strpd_s d0 = {}; #else /* !HAVE_SLOPPY_STRUCTS_INIT */ static const struct strpd_s d0; #endif /* HAVE_SLOPPY_STRUCTS_INIT */ struct dt_dt_s now = dt_get_base(); if (UNLIKELY(memcmp(&d.sd, &d0, sizeof(d0)) == 0U)) { goto msgg_time; } d.sd.y = now.d.ymd.y; if (LIKELY(d.sd.m)) { goto out; } d.sd.m = now.d.ymd.m; if (LIKELY(d.sd.d)) { goto out; } d.sd.d = now.d.ymd.d; msgg_time: /* same for time values, but obtain those through now_tv() */ if (UNLIKELY(!d.st.flags.h_set)) { d.st.h = now.t.hms.h; if (LIKELY(d.st.flags.m_set)) { goto out; } d.st.m = now.t.hms.m; if (LIKELY(d.st.flags.s_set)) { goto out; } d.st.s = now.t.hms.s; d.st.ns = now.t.hms.ns; } } out: return d; } #if defined WITH_LEAP_SECONDS static zidx_t leaps_before(struct dt_dt_s d) { zidx_t res; bool on; switch (d.typ) { case DT_YMD: res = leaps_before_ui32(leaps_ymd, nleaps, d.d.ymd.u); on = res + 1 < nleaps && leaps_ymd[res + 1] == d.d.ymd.u; break; case DT_YMCW: res = leaps_before_ui32(leaps_ymcw, nleaps, d.d.ymcw.u); on = res + 1 < nleaps && leaps_ymcw[res + 1] == d.d.ymcw.u; break; case DT_DAISY: res = leaps_before_ui32(leaps_d, nleaps, d.d.daisy); on = res + 1 < nleaps && leaps_d[res + 1] == d.d.daisy; break; case DT_SEXY: case DT_SEXYTAI: res = leaps_before_si32(leaps_s, nleaps, (int32_t)d.sexy); on = (res + 1U < nleaps) && (leaps_s[res + 1] == (int32_t)d.sexy); break; default: res = 0; on = false; break; } /* clang 3.3 will fuck the following up * see http://llvm.org/bugs/show_bug.cgi?id=18028 * we have to access d.t.hms.u24 once (the failing access), * then again and magically it'll work, thanks a bunch clang! */ if (dt_sandwich_p(d) && on) { #if defined __clang__ && __clang_major__ == 3 && __clang_minor__ >= 3 # warning clang bug! \ see http://llvm.org/bugs/show_bug.cgi?id=18028 /* access d.t.hms.u24 once */ volatile unsigned int hms = d.t.hms.u24; /* check the time part too */ if ((hms & 0xffffffU) > leaps_hms[res + 1]) { res++; } #else /* !__clang__ 3.3 */ /* check the time part too */ if (d.t.hms.u24 > leaps_hms[res + 1]) { res++; } #endif /* __clang__ 3.3 */ } return res; } #endif /* WITH_LEAP_SECONDS */ static inline int32_t zdiff_sec(struct dt_dt_s d) { /* obtain zdiff in signed seconds, instead of absolute ZDIFF_RES multiples */ int32_t zdiff = d.zdiff * ZDIFF_RES; if (d.neg) { zdiff = -zdiff; } return zdiff; } static inline __attribute__((const, pure)) bool dt_dur_only_d_p(struct dt_dtdur_s d) { return d.durtyp && d.d.durtyp < DT_NDURTYP && !d.t.sdur; } static bool need_milfup_p(const char *fmt) { /* military midnights don't need decaying if %T or %H is present */ for (const char *fp = fmt; *fp;) { const char *fp_sav = fp; struct dt_spec_s spec = __tok_spec(fp_sav, &fp); switch (spec.spfl) { case DT_SPFL_N_TSTD: return false; case DT_SPFL_N_HOUR: if (!spec.sc12) { return false; } default: break; } } return true; } /* parser implementations */ DEFUN struct dt_dt_s dt_strpdt(const char *str, const char *fmt, char **ep) { struct dt_dt_s res = dt_dt_initialiser(); struct strpdt_s d; const char *sp = str; const char *fp; if (LIKELY(fmt == NULL)) { return __strpdt_std(str, ep); } /* translate high-level format names, for sandwiches */ switch ((dt_dtyp_t)__trans_dtfmt(&fmt)) { char *on; default: break; /* special case julian/lilian dates as they have * no format specifiers */ case DT_JDN: /* we demand a float representation from start to finish */ res.d.jdn = (dt_jdn_t)strtod(str, &on); if (UNLIKELY(*on < '\0' || *on > ' ')) { /* nah, that's not a distinguished float */ goto fucked; } /* fix up const-ness problem */ sp = on; /* don't worry about time slot or date/time sandwiches */ dt_make_d_only(&res, DT_JDN); goto sober; case DT_LDN: res.d.ldn = (dt_ldn_t)strtoi(str, &sp); if (*sp == '.') { /* oooh, a double it seems */ double tmp = strtod(sp, &on); /* fix up const-ness problem */ sp = on; /* convert to HMS */ res.t.hms.h = (tmp *= HOURS_PER_DAY); tmp -= (double)res.t.hms.h; res.t.hms.m = (tmp *= MINS_PER_HOUR); tmp -= (double)res.t.hms.m; res.t.hms.s = (tmp *= SECS_PER_MIN); tmp -= (double)res.t.hms.s; res.t.hms.ns = (tmp *= NANOS_PER_SEC); dt_make_sandwich(&res, DT_LDN, DT_HMS); } else if (UNLIKELY(*sp < '\0' || *sp > ' ')) { /* not on my turf */ goto fucked; } else { /* looking good */ dt_make_d_only(&res, DT_LDN); } goto sober; case DT_MDN: res.d.mdn = (dt_ldn_t)strtoi(str, &sp); if (*sp == '.') { /* oooh, a double it seems */ double tmp = strtod(sp, &on); /* fix up const-ness problem */ sp = on; /* convert to HMS */ res.t.hms.h = (tmp *= HOURS_PER_DAY); tmp -= (double)res.t.hms.h; res.t.hms.m = (tmp *= MINS_PER_HOUR); tmp -= (double)res.t.hms.m; res.t.hms.s = (tmp *= SECS_PER_MIN); tmp -= (double)res.t.hms.s; res.t.hms.ns = (tmp *= NANOS_PER_SEC); dt_make_sandwich(&res, DT_MDN, DT_HMS); } else if (UNLIKELY(*sp < '\0' || *sp > ' ')) { /* not on my turf */ goto fucked; } else { /* looking good */ dt_make_d_only(&res, DT_MDN); } goto sober; } fp = fmt; d = strpdt_initialiser(); while (*fp && *sp) { const char *fp_sav = fp; struct dt_spec_s spec = __tok_spec(fp_sav, &fp); if (spec.spfl == DT_SPFL_UNK) { /* must be literal */ if (*fp_sav != *sp++) { goto fucked; } } else if (LIKELY(!spec.rom)) { const char *sp_sav = sp; if (__strpdt_card(&d, sp, spec, (char**)&sp) < 0) { goto fucked; } if (spec.ord && __ordinalp(sp_sav, sp - sp_sav, (char**)&sp) < 0) { ; } if (spec.bizda) { switch (*sp++) { case 'B': d.sd.flags.ab = BIZDA_BEFORE; case 'b': d.sd.flags.bizda = 1; break; default: /* it's a bizda anyway */ d.sd.flags.bizda = 1; sp--; break; } } } else if (UNLIKELY(spec.rom)) { if (__strpd_rom(&d.sd, sp, spec, (char**)&sp) < 0) { goto fucked; } } } /* check suffix literal */ if (*fp && *fp != *sp) { goto fucked; } /* check if it's a sexy type */ if (d.i) { res.typ = DT_SEXY; res.sexy = d.i; } else { /* assign d and t types using date and time core routines */ d = massage_strpdt(d); res.d = __guess_dtyp(d.sd); res.t = __guess_ttyp(d.st); if (res.d.typ > DT_DUNK && res.t.typ > DT_TUNK) { res.sandwich = 1; } else if (res.d.typ > DT_DUNK) { res.t.typ = DT_TUNK; res.sandwich = 0; } else if (res.t.typ > DT_TUNK) { res.d.typ = DT_DUNK; res.sandwich = 1; } } if (d.zdiff && dt_sandwich_p(res)) { res = __fixup_zdiff(res, d.zdiff); } else if (d.zngvn && dt_sandwich_p(res)) { res.znfxd = 1; } sober: /* set the end pointer */ if (ep != NULL) { *ep = (char*)sp; } return res; fucked: if (ep != NULL) { *ep = (char*)str; } return dt_dt_initialiser(); } DEFUN size_t dt_strfdt(char *restrict buf, size_t bsz, const char *fmt, struct dt_dt_s that) { struct strpdt_s d = strpdt_initialiser(); const char *fp; char *bp; dt_dtyp_t tgttyp; int set_fmt = 0; if (UNLIKELY(buf == NULL || bsz == 0)) { bp = buf; goto out; } if (LIKELY(fmt == NULL)) { /* um, great */ set_fmt = 1; } else if (LIKELY(*fmt == '%')) { /* don't worry about it */ ; } else if ((tgttyp = __trans_dfmt_special(fmt)) != (dt_dtyp_t)DT_UNK) { that = dt_dtconv((dt_dttyp_t)tgttyp, that); set_fmt = 1; } if (set_fmt && dt_sandwich_p(that)) { switch (that.typ) { case DT_YMD: fmt = ymdhms_dflt; break; case DT_YMCW: fmt = ymcwhms_dflt; break; case DT_YWD: fmt = ywdhms_dflt; break; case DT_YD: fmt = ydhms_dflt; break; case DT_DAISY: /* subject to change */ fmt = ymdhms_dflt; break; case DT_JDN: case DT_LDN: case DT_MDN: strf_xian: /* short cut, just print the guy here */ bp = buf + __strfdt_xdn(buf, bsz, that); goto out; case DT_BIZDA: fmt = bizdahms_dflt; break; case DT_SEXY: case DT_YMDHMS: fmt = ymdhms_dflt; break; default: /* fuck */ abort(); break; } } else if (set_fmt && dt_sandwich_only_d_p(that)) { switch (that.d.typ) { case DT_YMD: fmt = ymd_dflt; break; case DT_YMCW: fmt = ymcw_dflt; break; case DT_YWD: fmt = ywd_dflt; break; case DT_YD: fmt = yd_dflt; break; case DT_DAISY: /* subject to change */ fmt = ymd_dflt; break; case DT_BIZDA: fmt = bizda_dflt; break; case DT_JDN: case DT_LDN: case DT_MDN: goto strf_xian; default: /* fuck */ abort(); break; } } else if (set_fmt && that.typ >= DT_PACK && that.typ < DT_NDTTYP) { /* must be sexy or ymdhms */ fmt = ymdhms_dflt; } else if (dt_sandwich_only_t_p(that)) { /* transform time specs */ __trans_tfmt(&fmt); } /* fix up before printing */ if (LIKELY(dt_sandwich_p(that) || dt_sandwich_only_d_p(that))) { that.d = dt_dfixup(that.d); } /* make sure we always snarf the zdiff info */ d.zdiff = zdiff_sec(that); if (dt_sandwich_p(that) && UNLIKELY(that.t.hms.h == 24U)) { /* military midnight fixup * only when there's %H or %T in the flags, don't decay*/ if (need_milfup_p(fmt)) { that = dt_milfup(that); } } switch (that.typ) { case DT_YMD: ymd_prep: d.sd.y = that.d.ymd.y; d.sd.m = that.d.ymd.m; d.sd.d = that.d.ymd.d; break; case DT_YMCW: d.sd.y = that.d.ymcw.y; d.sd.m = that.d.ymcw.m; d.sd.c = that.d.ymcw.c; d.sd.w = that.d.ymcw.w; break; case DT_YWD: __prep_strfd_ywd(&d.sd, that.d.ywd); break; case DT_YD: d.sd.y = that.d.yd.y; d.sd.d = that.d.yd.d; d.sd.flags.d_dcnt_p = 1U; break; case DT_JDN: that = dt_dtconv((dt_dttyp_t)DT_DAISY, that); goto daisy_prep; case DT_LDN: that = dt_dtconv((dt_dttyp_t)DT_DAISY, that); goto daisy_prep; case DT_MDN: that = dt_dtconv((dt_dttyp_t)DT_DAISY, that); goto daisy_prep; case DT_DAISY: daisy_prep: __prep_strfd_daisy(&d.sd, that.d.daisy); break; case DT_BIZDA: __prep_strfd_bizda( &d.sd, that.d.bizda, __get_bizda_param(that.d)); break; case DT_SEXY: /* instead of leaving this as SEXY turn it into * DAISY/HMS sandwich */ that = dt_dtconv((dt_dttyp_t)DT_DAISY, that); /* prep d.sd */ goto daisy_prep; case DT_YMDHMS: /* convert this to a YMD/HMS sandwich */ that = dt_dtconv((dt_dttyp_t)DT_YMD, that); /* prep d.sd */ goto ymd_prep; default: case DT_DUNK: if (!dt_sandwich_only_t_p(that)) { bp = buf; goto out; } } if (dt_sandwich_p(that) || dt_sandwich_only_t_p(that)) { /* cope with the time part */ d.st.h = that.t.hms.h; d.st.m = that.t.hms.m; d.st.s = that.t.hms.s; d.st.ns = that.t.hms.ns; } /* assign and go */ bp = buf; fp = fmt; for (char *const eo = buf + bsz; *fp && bp < eo;) { const char *fp_sav = fp; struct dt_spec_s spec = __tok_spec(fp_sav, &fp); if (spec.spfl == DT_SPFL_UNK) { /* must be literal then */ *bp++ = *fp_sav; } else if (LIKELY(!spec.rom)) { bp += __strfdt_card(bp, eo - bp, spec, &d, that); if (spec.ord) { bp += __ordtostr(bp, eo - bp); } else if (spec.bizda) { /* don't print the b after an ordinal */ if (spec.ab == BIZDA_AFTER) { *bp++ = 'b'; } else { *bp++ = 'B'; } } } else if (UNLIKELY(spec.rom)) { bp += __strfd_rom(bp, eo - bp, spec, &d.sd, that.d); } } out: if (bp < buf + bsz) { *bp = '\0'; } return bp - buf; } DEFUN struct dt_dtdur_s dt_strpdtdur(const char *str, char **ep) { /* at the moment we allow only one format */ struct dt_dtdur_s res = {(dt_dtdurtyp_t)DT_DURUNK}; const char *sp; long int tmp; if ((sp = str) == NULL) { goto out; } /* read off co-class indicator */ if (*sp == '/') { res.cocl = 1U; sp++; } /* read just one component, use rudi's errno trick */ errno = 0; if ((tmp = strtol(str, (char**)&sp, 10)) == 0 && str == sp) { /* didn't work aye? */ goto out; } else if (tmp > INT_MAX || errno) { errno = ERANGE; goto out; } sp: switch (*sp++) { case '\0': /* must have been day then */ res.d.durtyp = DT_DURD; sp--; break; case 'd': case 'D': res.d.durtyp = DT_DURD; break; case 'y': case 'Y': res.d.durtyp = DT_DURYR; break; case 'w': case 'W': res.d.durtyp = DT_DURWK; break; case 'b': case 'B': res.d.durtyp = DT_DURBD; break; case 'q': case 'Q': res.d.durtyp = DT_DURQU; break; case 'h': case 'H': res.durtyp = DT_DURH; break; case 'm': case 'M': if (*sp == 'o') { /* that makes it a month */ res.d.durtyp = DT_DURMO; sp++; break; } /*@fallthrough@*/ case '\'': res.durtyp = DT_DURM; break; case 's': case 'S': case '"': res.durtyp = DT_DURS; break; case 'r': /* real seconds/hours/minutes */ res.tai = 1; goto sp; case 'n': res.durtyp = DT_DURNANO; if (*sp == 's') { /* nanoseconds, my favourite */ sp++; } break; default: sp = str; goto out; } /* no further checks on tmp */ if (res.durtyp < (unsigned int)DT_NDURTYP) { res.d.dv = tmp; } else { res.dv = tmp; } out: if (ep != NULL) { *ep = (char*)sp; } return res; } DEFUN size_t dt_strfdtdur( char *restrict buf, size_t bsz, const char *fmt, struct dt_dtdur_s that) { struct strpdt_s d; const char *fp; char *bp; if (UNLIKELY(buf == NULL || bsz == 0)) { bp = buf; goto out; } d = strpdt_initialiser(); switch (that.d.durtyp) { case DT_YMD: d.sd.y = that.d.ymd.y; d.sd.m = that.d.ymd.m; d.sd.d = that.d.ymd.d; if (fmt == NULL && !dt_dur_only_d_p(that)) { fmt = ymdhmsdur_dflt; } else if (fmt == NULL && dt_dur_only_d_p(that)) { fmt = ymddur_dflt; } else if (fmt == NULL) { goto try_time; } break; case DT_YMCW: d.sd.y = that.d.ymcw.y; d.sd.m = that.d.ymcw.m; d.sd.c = that.d.ymcw.c; d.sd.d = that.d.ymcw.w; if (fmt == NULL && !dt_dur_only_d_p(that)) { fmt = ymcwhmsdur_dflt; } else if (fmt == NULL && dt_dur_only_d_p(that)) { fmt = ymcwdur_dflt; } else if (fmt == NULL) { goto try_time; } break; case DT_YWD: d.sd.y = that.d.ywd.y; d.sd.c = that.d.ywd.c; d.sd.d = that.d.ywd.w; if (fmt == NULL && !dt_dur_only_d_p(that)) { fmt = ywdhmsdur_dflt; } else if (fmt == NULL && dt_dur_only_d_p(that)) { fmt = ywddur_dflt; } else if (fmt == NULL) { goto try_time; } break; case DT_YD: d.sd.y = that.d.yd.y; d.sd.d = that.d.yd.d; if (fmt == NULL && !dt_dur_only_d_p(that)) { fmt = ydhmsdur_dflt; } else if (fmt == NULL && dt_dur_only_d_p(that)) { fmt = yddur_dflt; } else if (fmt == NULL) { goto try_time; } break; case DT_DURD: d.sd.d = that.d.dv; if (fmt == NULL) { fmt = daisydur_dflt; } break; case DT_DURBD: d.sd.d = that.d.dv; if (fmt == NULL) { /* subject to change */ fmt = bizsidur_dflt; } break; case DT_BIZDA:; dt_bizda_param_t bparam; bparam.bs = that.d.param; d.sd.y = that.d.bizda.y; d.sd.m = that.d.bizda.m; d.sd.b = that.d.bizda.bd; if (LIKELY(bparam.ab == BIZDA_AFTER)) { d.sd.flags.ab = BIZDA_AFTER; } else { d.sd.flags.ab = BIZDA_BEFORE; } d.sd.flags.bizda = 1; if (fmt == NULL && !dt_dur_only_d_p(that)) { fmt = bizdahmsdur_dflt; } else if (fmt == NULL && dt_dur_only_d_p(that)) { fmt = bizdadur_dflt; } else if (fmt == NULL) { goto try_time; } break; default: case DT_DUNK: break; } /* translate high-level format names */ if (!dt_dur_only_d_p(that)) { __trans_dtdurfmt(&fmt); } else if (dt_dur_only_d_p(that)) { __trans_ddurfmt(&fmt); } else if (true) { try_time: fmt = "%S"; } else { bp = buf; goto out; } /* assign and go */ bp = buf; fp = fmt; if (that.d.neg) { *bp++ = '-'; } for (char *const eo = buf + bsz; *fp && bp < eo;) { const char *fp_sav = fp; struct dt_spec_s spec = __tok_spec(fp_sav, &fp); if (spec.spfl == DT_SPFL_UNK) { /* must be literal then */ *bp++ = *fp_sav; } else if (LIKELY(!spec.rom)) { bp += __strfdt_dur(bp, eo - bp, spec, &d, that); if (spec.bizda) { /* don't print the b after an ordinal */ if (d.sd.flags.ab == BIZDA_AFTER) { *bp++ = 'b'; } else { *bp++ = 'B'; } } } } out: if (bp < buf + bsz) { *bp = '\0'; } return bp - buf; } DEFUN struct dt_dtdur_s dt_neg_dtdur(struct dt_dtdur_s dur) { dur.neg = (uint16_t)(~dur.neg & 0x01); dur.t.neg = (uint16_t)(~dur.t.neg & 0x01); switch (dur.durtyp) { case DT_DURD: case DT_DURBD: case DT_DURWK: case DT_DURMO: case DT_DURQU: case DT_DURYR: dur.d.dv = -dur.d.dv; dur.t.sdur = -dur.t.sdur; break; case DT_DURH: case DT_DURM: case DT_DURS: case DT_DURNANO: dur.dv = -dur.dv; break; default: break; } return dur; } DEFUN int dt_dtdur_neg_p(struct dt_dtdur_s dur) { switch (dur.durtyp) { case DT_DURD: case DT_DURBD: case DT_DURWK: case DT_DURMO: case DT_DURQU: case DT_DURYR: return dur.d.dv < 0 || (!dur.d.dv && dur.t.sdur < 0); case DT_DURH: case DT_DURM: case DT_DURS: case DT_DURNANO: return dur.dv < 0; default: break; } return dur.neg; } /* date getters, platform dependent */ DEFUN struct dt_dt_s dt_datetime(dt_dttyp_t outtyp) { struct dt_dt_s res = dt_dt_initialiser(); const dt_dtyp_t outdtyp = (dt_dtyp_t)outtyp; struct tm tm = now_tm(); struct timeval tv = now_tv(); switch (outdtyp) { case DT_YMD: case DT_YMCW: case DT_YD: switch (outdtyp) { case DT_YMD: res.d.ymd.y = tm.tm_year; res.d.ymd.m = tm.tm_mon; res.d.ymd.d = tm.tm_mday; break; case DT_YMCW: { #if defined HAVE_ANON_STRUCTS_INIT dt_ymd_t tmp = { .y = tm.tm_year, .m = tm.tm_mon, .d = tm.tm_mday, }; #else dt_ymd_t tmp; tmp.y = tm.tm_year, tmp.m = tm.tm_mon, tmp.d = tm.tm_mday, #endif res.d.ymcw.y = tm.tm_year; res.d.ymcw.m = tm.tm_mon; res.d.ymcw.c = __ymd_get_count(tmp); res.d.ymcw.w = tm.tm_wday; break; } case DT_YD: res.d.yd.y = tm.tm_year; res.d.yd.d = tm.tm_yday; break; default: /* grrrr */ ; } break; case DT_YWD: /* use ordinary conversion to ywd */ res.d.typ = DT_YMD; res.d.ymd.y = tm.tm_year; res.d.ymd.m = tm.tm_mon; res.d.ymd.d = tm.tm_mday; res.d = dt_dconv(DT_YWD, res.d); break; case DT_DAISY: /* time_t's base is 1970-01-01, which is daisy 19359 */ res.d.daisy = tv.tv_sec / (unsigned int)SECS_PER_DAY + DAISY_UNIX_BASE; break; case DT_BIZDA: case DT_BIZSI: /* could be an idea to have those, innit? */ default: case DT_DUNK: break; } /* time assignment */ if (outdtyp <= DT_NDTYP) { res.t.hms.h = tm.tm_hour; res.t.hms.m = tm.tm_min; res.t.hms.s = tm.tm_sec; res.t.hms.ns = tv.tv_usec * 1000; dt_make_sandwich(&res, (dt_dtyp_t)outtyp, DT_HMS); } else { /* must be one of the sexies then, aye? */ res.sexy = tv.tv_sec; } return res; } DEFUN struct dt_dt_s dt_dtconv(dt_dttyp_t tgttyp, struct dt_dt_s d) { if (dt_sandwich_p(d) || dt_sandwich_only_d_p(d)) { /* thanks gcc for making me cast tgttyp */ switch ((unsigned int)tgttyp) { short unsigned int sw; case DT_YMD: case DT_YMCW: case DT_BIZDA: case DT_DAISY: case DT_BIZSI: case DT_YWD: case DT_YD: case DT_JDN: case DT_LDN: case DT_MDN: /* backup sandwich state */ sw = d.sandwich; /* convert */ d.d = dt_dconv((dt_dtyp_t)tgttyp, d.d); /* restore sandwich state */ d.sandwich = sw; break; case DT_SEXY: case DT_SEXYTAI: { dt_daisy_t dd = dt_conv_to_daisy(d.d); unsigned int ss = __secs_since_midnight(d.t); switch (tgttyp) { int32_t sx; #if defined WITH_LEAP_SECONDS case DT_SEXYTAI: { zidx_t zi; sx = (dd - DAISY_UNIX_BASE) * SECS_PER_DAY + ss; zi = leaps_before_si32(leaps_s, nleaps, sx); d.sexy = sx + leaps_corr[zi]; break; } #else /* !WITH_LEAP_SECONDS */ case DT_SEXYTAI: #endif /* WITH_LEAP_SECONDS */ case DT_SEXY: sx = (dd - DAISY_UNIX_BASE) * SECS_PER_DAY + ss; d.sexy = sx; break; default: /* grrrr */ ; } d.sandwich = 0; d.typ = tgttyp; break; } case DT_YMDHMS: /* no support for this guy yet */ case DT_DUNK: default: d = dt_dt_initialiser(); break; } } else if (dt_sandwich_only_t_p(d)) { /* ah, how good is that? */ ; } else if (!dt_separable_p(d)) { switch (d.typ) { case DT_SEXY: case DT_SEXYTAI: if (tgttyp > DT_UNK && tgttyp < DT_PACK) { /* go through daisy */ d = __sexy_to_daisy(d.sxepoch); d.d = dt_dconv((dt_dtyp_t)tgttyp, d.d); d.sandwich = 1U; } else if (tgttyp == DT_YMDHMS) { ; } break; case DT_YMDHMS: if (tgttyp > DT_UNK && tgttyp < DT_PACK) { /* go through ymd */ d = __ymdhms_to_ymd(d.ymdhms); d.d = dt_dconv((dt_dtyp_t)tgttyp, d.d); d.sandwich = 1U; } else if (tgttyp == DT_SEXY) { ; } break; default: d = dt_dt_initialiser(); break; } } else { /* great, what now? */ ; } return d; } DEFUN struct dt_dt_s dt_dtadd(struct dt_dt_s d, struct dt_dtdur_s dur) { /* we decompose the problem like so: * carry <- dpart(dur); * tpart(res), carry <- tadd(d, tpart(dur), corr); * res <- dadd(dpart(res), carry); */ dt_ssexy_t dv; #if defined WITH_LEAP_SECONDS struct dt_dt_s orig; const bool tai_fixup_p = dur.tai && !dt_sandwich_only_d_p(d); if (UNLIKELY(tai_fixup_p)) { /* make a copy */ orig = d; } #endif /* WITH_LEAP_SECONDS */ if (d.typ == DT_SEXY) { d.sexy = __sexy_add(d.sexy, dur); return d; } dv = dur.dv; switch (dur.durtyp) { default: dadd: /* let date-core's dt_dadd() do the yakka */ d.d = dt_dadd(d.d, dur.d); break; case DT_DURH: dv *= MINS_PER_HOUR; /*@fallthrough@*/ case DT_DURM: dv *= SECS_PER_MIN; /*@fallthrough@*/ case DT_DURS:; int carry; tadd: /* make sure we don't blow the carry slot */ carry = dv / (signed int)SECS_PER_DAY; dv = dv % (signed int)SECS_PER_DAY; if (d.sandwich) { /* accept both t-onlies and sandwiches */ d.t = dt_tadd_s(d.t, dv, 0); if ((carry += d.t.carry) && !dt_sandwich_only_t_p(d)) { /* add some days as well */ dur.d.durtyp = DT_DURD; dur.d.dv = carry; goto dadd; } } break; case DT_DURNANO:; /* quickly do the addition ourselves */ dv += d.t.hms.ns; carry = dv / (signed int)NANOS_PER_SEC; if ((dv = dv % (signed int)NANOS_PER_SEC) < 0) { dv += NANOS_PER_SEC; carry--; } d.t.hms.ns = dv; /* the rest is normal second-wise tadd */ dv = carry; goto tadd; } #if defined WITH_LEAP_SECONDS if (UNLIKELY(tai_fixup_p)) { /* the reason we omitted SEXY is because there's simply * no representation in there */ zidx_t i_orig = leaps_before(orig); zidx_t i_d = leaps_before(d); if (UNLIKELY(i_orig != i_d)) { /* insert leaps */ int nltr = leaps_corr[i_orig] - leaps_corr[i_d]; /* save a copy of d again */ orig = d; i_orig = i_d; if (nltr && /* get our special tadd with carry */ (d.t = dt_tadd_s(d.t, nltr, 0), d.t.carry)) { /* great, we need to sub/add again * as there's been a wrap-around at * midnight, spooky */ dur.d.durtyp = DT_DURD; dur.d.dv = d.t.carry; d.d = dt_dadd(d.d, dur.d); } /* check if we transitioned again */ if (d.typ == DT_SEXYTAI || (i_d = leaps_before(d), 0)) { /* don't have to */ ; } else if (UNLIKELY(i_d < i_orig)) { d.t.hms.s -= nltr; } else if (UNLIKELY(i_d > i_orig)) { d = orig; d.t.hms.s += nltr; } } } #endif /* WITH_LEAP_SECONDS */ return d; } DEFUN struct dt_dtdur_s dt_dtdiff(dt_dtdurtyp_t tgttyp, struct dt_dt_s d1, struct dt_dt_s d2) { struct dt_dtdur_s res = {(dt_dtdurtyp_t)DT_DURUNK}; int dt = 0; if (!dt_sandwich_only_d_p(d1) && !dt_sandwich_only_d_p(d2)) { /* do the time portion difference right away */ dt = dt_tdiff_s(d1.t, d2.t); } /* now assess what else is to be done */ if (dt_sandwich_only_t_p(d1) && dt_sandwich_only_t_p(d2)) { /* make t-only */ res.durtyp = DT_DURS; res.dv = dt; } else if (tgttyp && (dt_durtyp_t)tgttyp < DT_NDURTYP) { /* check for negative carry */ if (UNLIKELY(dt < 0)) { d2.d = dt_dadd(d2.d, dt_make_ddur(DT_DURD, -1)); dt += SECS_PER_DAY; } res.durtyp = tgttyp; res.d = dt_ddiff((dt_durtyp_t)tgttyp, d1.d, d2.d); res.t.sdur = dt; } else if ((dt_durtyp_t)tgttyp >= DT_NDURTYP) { int64_t sxdur; if (d1.typ < DT_PACK && d2.typ < DT_PACK) { /* go for tdiff and ddiff independently */ res.d = dt_ddiff(DT_DURD, d1.d, d2.d); /* since target type is SEXY do the conversion here */ sxdur = (int64_t)dt + (int64_t)res.d.dv * SECS_PER_DAY; } else { /* oh we're in the sexy domain already, * note, we can't diff ymdhms packs */ d1 = dt_dtconv(DT_SEXY, d1); d2 = dt_dtconv(DT_SEXY, d2); /* now it's fuck-easy */ sxdur = d2.sexy - d1.sexy; } /* set up the output here */ res.durtyp = tgttyp; res.neg = 0U; if (LIKELY(tgttyp < DT_NDTDURTYP)) { res.tai = 0U; } else { /* just a hack to transfer the notion of TAIness */ res.tai = 1U; res.durtyp = DT_DURS; } res.dv = sxdur; #if defined WITH_LEAP_SECONDS if (tgttyp >= DT_NDTDURTYP) { /* just a hack to transfer the notion of TAIness * check for transitions */ zidx_t i_d1 = leaps_before(d1); zidx_t i_d2 = leaps_before(d2); # if BYTE_ORDER == BIG_ENDIAN /* not needed on little-endians * the little means just that */ res.soft = sxdur; # elif BYTE_ORDER == LITTLE_ENDIAN # else # warning unknown byte order # endif /* BYTE_ORDER */ if (UNLIKELY(i_d1 != i_d2)) { int nltr = leaps_corr[i_d2] - leaps_corr[i_d1]; res.corr = nltr; # if BYTE_ORDER == BIG_ENDIAN } else { /* always repack res.corr to remove clutter * from the earlier res.sexydur ass'ment */ res.corr = 0; # elif BYTE_ORDER == LITTLE_ENDIAN # else # warning unknown byte order # endif /* BYTE_ORDER */ } } #endif /* WITH_LEAP_SECONDS */ } return res; } DEFUN int dt_dtcmp(struct dt_dt_s d1, struct dt_dt_s d2) { /* for the moment D1 and D2 have to be of the same type. */ if (UNLIKELY(d1.typ != d2.typ)) { /* always equal */ return -2; } /* go through it hierarchically and without upmotes */ switch (d1.d.typ) { int res; case DT_DUNK: default: goto try_time; case DT_YMD: case DT_DAISY: case DT_BIZDA: case DT_YWD: case DT_YD: /* use arithmetic comparison */ if (d1.d.u < d2.d.u) { return -1; } else if (d1.d.u > d2.d.u) { return 1; } else { /* means they're equal, so try the time part */ goto try_time; } case DT_YMCW: /* use designated thing since ymcw dates aren't * increasing */ if (!(res = __ymcw_cmp(d1.d.ymcw, d2.d.ymcw))) { goto try_time; } return res; } try_time: if (d1.t.hms.u < d2.t.hms.u) { return -1; } else if (d1.t.hms.u > d2.t.hms.u) { return 1; } return 0; } DEFUN int dt_dt_in_range_p(struct dt_dt_s d, struct dt_dt_s d1, struct dt_dt_s d2) { /* use the following multiplication table * * |d,d2|v |d,d1|> -2 -1 0 1 * -2 -1 -1 -1 -1 * -1 -1 0 1 1 * 0 -1 0 1 1 * 1 -1 0 0 0 * * encoded in a 32bit uint */ static const uint32_t m = 0b10010111100101111010101111111111U; const unsigned int i = (dt_dtcmp(d, d1) + 2) & 0b11U; const unsigned int j = (dt_dtcmp(d, d2) + 2) & 0b11U; return 2 - ((m >> (i * 8U + j * 2U)) & 0b11U); } #if defined __INTEL_COMPILER # pragma warning (default:2203) #elif defined __GNUC__ # pragma GCC diagnostic warning "-Wcast-qual" #endif /* __INTEL_COMPILER */ static struct dt_dt_s base; DEFUN void dt_set_base(struct dt_dt_s dt) { if (UNLIKELY(dt.typ != (dt_dttyp_t)DT_YMD)) { dt = dt_dtconv((dt_dttyp_t)DT_YMD, dt); } base = dt; return; } DEFUN struct dt_dt_s dt_get_base(void) { if (UNLIKELY(base.typ == DT_UNK)) { /* singleton */ base = dt_datetime((dt_dttyp_t)DT_YMD); } return base; } #if defined LIBDUT # if defined INCLUDED_date_core_h_ /* service routines */ DEFUN struct dt_d_s dt_get_dbase(void) { struct dt_dt_s b = dt_get_base(); return b.d; } # endif /* INCLUDED_date_core_h_ */ # if defined INCLUDED_time_core_h_ /* service routines */ DEFUN struct dt_t_s dt_get_tbase(void) { struct dt_dt_s b = dt_get_base(); return b.t; } # endif /* INCLUDED_time_core_h_ */ #endif /* LIBDUT */ DEFUN __attribute__((pure)) struct dt_dt_s dt_fixup(struct dt_dt_s d) { if (LIKELY(dt_sandwich_only_d_p(d) || dt_sandwich_p(d))) { d.d = dt_dfixup(d.d); } return d; } DEFUN __attribute__((pure)) struct dt_dt_s dt_milfup(struct dt_dt_s dt) { if (dt_sandwich_p(dt) && UNLIKELY(dt.t.hms.h == 24)) { dt = dt_dtadd(dt, (struct dt_dtdur_s){DT_DURS}); } return dt; } #endif /* INCLUDED_date_core_c_ */ /* dt-core.c ends here */ dateutils-0.4.5/lib/dt-core.h000066400000000000000000000253021335042257000157750ustar00rootroot00000000000000/*** dt-core.h -- our universe of datetimes * * Copyright (C) 2011-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of dateutils. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * **/ #if !defined INCLUDED_dt_core_h_ #define INCLUDED_dt_core_h_ #include #include #include #include #include "boops.h" #include "date-core.h" #include "time-core.h" typedef enum { /* this one's our own version of UNK */ DT_UNK = 0, /* the lower date types come from date-core.h */ DT_PACK = DT_NDTYP, DT_YMDHMS = DT_PACK, DT_SEXY, DT_SEXYTAI, DT_NDTTYP, } dt_dttyp_t; typedef enum { DT_DURH = DT_NDURTYP + 0U, DT_DURM = DT_NDURTYP + 1U, DT_DURS = DT_NDURTYP + 2U, DT_DURNANO = DT_NDURTYP + 3U, } dt_dtdurtyp_t; /* this will be 16 and hence must be #defined as we're using * a bitfield of size 4 to store the dtdurtyp. */ #define DT_NDTDURTYP (DT_NDURTYP + 4U) /** packs * packs are just packs of dates and times */ typedef union { uint64_t u:53; struct { #if BYTE_ORDER == BIG_ENDIAN #define DT_YEAR_OFFS (1900) /* offset by the year 1900 */ unsigned int y:12; unsigned int m:4; unsigned int d:5; /* round up to 32 bits, remaining bits are seconds east */ unsigned int offs:11; /* time part */ unsigned int H:5; unsigned int M:8; unsigned int S:8; #elif BYTE_ORDER == LITTLE_ENDIAN unsigned int d:5; unsigned int m:4; /* offset by the year 1900 */ #define DT_YEAR_OFFS (1900) unsigned int y:12; /* round up to 32 bits, remaining bits are seconds east */ unsigned int offs:11; /* time part */ unsigned int S:8; unsigned int M:8; unsigned int H:5; #else # warning unknown byte order #endif /* BYTE_ORDER */ }; } dt_ymdhms_t; /** sexy * sexy is really, secsi, seconds since X, 1970-01-01T00:00:00 here */ typedef uint64_t dt_sexy_t; typedef int64_t dt_ssexy_t; #define DT_SEXY_BASE_YEAR (1917) struct dt_dt_s { union { /* packs */ struct { /* dt type, or date type */ dt_dttyp_t typ:4; /* sandwich indicator (use d and t slots below) */ uint16_t sandwich:1; /* whether we had zone info already but fixed it */ uint16_t znfxd:1; /* whether to be aware of leap-seconds */ uint16_t tai:1; /* error indicator to denote date has been fixed up */ uint16_t fix:1; /* was duration indicator */ uint16_t xxx:1; /* negation indicator */ uint16_t neg:1; /* we've got 6 bits left here to coincide with dt_d_s * use that and the neg flag for zdiffs * zdiff itself has 15-minute resolution, * range [0, 63] aka [00:00 16:00] * The policy is to store the time always in UTC * but keep the difference in this slot. */ uint16_t zdiff:6; #define ZDIFF_RES (15U * 60U) union { uint64_t u:48; dt_ymdhms_t ymdhms; dt_sexy_t sexy:48; dt_ssexy_t sxepoch:48; struct { #if BYTE_ORDER == BIG_ENDIAN int32_t corr:16; int32_t soft:32; #elif BYTE_ORDER == LITTLE_ENDIAN int32_t soft:32; int32_t corr:16; #else # warning unknown byte order #endif /* BYTE_ORDER */ }; }; } __attribute__((packed)); /* sandwich types */ struct { struct dt_d_s d; struct dt_t_s t; }; }; }; struct dt_dtdur_s { union { /* packs */ struct { /* dt type, or date type */ dt_dtdurtyp_t durtyp:4; /* was sandwich indicator */ uint16_t:1; /* whether we had zone info already but fixed it */ uint16_t znfxd:1; /* whether to be aware of leap-seconds */ uint16_t tai:1; /* error indicator to denote date has been fixed up */ uint16_t fix:1; /* co-class indicator */ uint16_t cocl:1; /* negation indicator */ uint16_t neg:1; /* we've got 6 bits left here to coincide with dt_d_s * use that and the neg flag for zdiffs * zdiff itself has 15-minute resolution, * range [0, 63] aka [00:00 16:00] * The policy is to store the time always in UTC * but keep the difference in this slot. */ uint16_t zdiff:6; #define ZDIFF_RES (15U * 60U) union { uint64_t u:48; dt_ymdhms_t ymdhms; /* for value+unit durations */ dt_ssexy_t dv:48; struct { #if BYTE_ORDER == BIG_ENDIAN int32_t corr:16; int32_t soft:32; #elif BYTE_ORDER == LITTLE_ENDIAN int32_t soft:32; int32_t corr:16; #else # warning unknown byte order #endif /* BYTE_ORDER */ }; }; } __attribute__((packed)); /* sandwich types */ struct { struct dt_ddur_s d; struct dt_t_s t; }; }; }; /* decls */ /** * Like strptime() for our dates. * The format characters are _NOT_ compatible with strptime(). * If FMT is NULL the standard format for each calendric system is used, * see format.texi or dateutils info page. * * FMT can also be the name of a calendar: * - ymd for YMD dates * - ymcw for YMCW dates * - bizda for bizda/YMDU dates * * If optional EP is non-NULL it will point to the end of the parsed * date string. */ extern struct dt_dt_s dt_strpdt(const char *str, const char *fmt, char **ep); /** * Like strftime() for our dates */ extern size_t dt_strfdt(char *restrict buf, size_t bsz, const char *fmt, struct dt_dt_s); /** * Parse durations as in 1w5d, etc. */ extern struct dt_dtdur_s dt_strpdtdur(const char *str, char **ep); /** * Print a duration. */ extern size_t dt_strfdtdur(char *restrict buf, size_t bsz, const char *fmt, struct dt_dtdur_s); /** * Negate the duration. */ extern struct dt_dtdur_s dt_neg_dtdur(struct dt_dtdur_s); /** * Is duration DUR negative? */ extern int dt_dtdur_neg_p(struct dt_dtdur_s dur); /** * Like time() but return the current date in the desired format. */ extern struct dt_dt_s dt_datetime(dt_dttyp_t dttyp); /** * Convert D to another calendric system, specified by TGTTYP. */ extern struct dt_dt_s dt_dtconv(dt_dttyp_t tgttyp, struct dt_dt_s); /** * Add duration DUR to date/time D. * The result will be in the calendar as specified by TGTTYP, or if * DT_UNK is given, the calendar of D will be used. */ extern struct dt_dt_s dt_dtadd(struct dt_dt_s d, struct dt_dtdur_s dur); /** * Get duration between D1 and D2. * The result will be of type TGTTYP, * the calendar of D1 will be used, e.g. its month-per-year, days-per-week, * etc. conventions count. * If instead D2 should count, swap D1 and D2 and negate the duration * by setting/clearing the neg bit. */ extern struct dt_dtdur_s dt_dtdiff(dt_dtdurtyp_t tgttyp, struct dt_dt_s d1, struct dt_dt_s d2); /** * Compare two dates, yielding 0 if they are equal, -1 if D1 is older, * 1 if D1 is younger than the D2. */ extern int dt_dtcmp(struct dt_dt_s d1, struct dt_dt_s d2); /** * Check if D is in the interval spanned by D1 and D2, * 1 if D1 is younger than the D2. */ extern int dt_dt_in_range_p(struct dt_dt_s d, struct dt_dt_s d1, struct dt_dt_s d2); /* more specific but still useful functions */ /** * Convert a dt_dt_s to an epoch difference, based on the Unix epoch. */ extern dt_ssexy_t dt_to_unix_epoch(struct dt_dt_s); /** * Convert a dt_dt_s to an epoch difference, based on the GPS epoch. */ extern dt_ssexy_t dt_to_gps_epoch(struct dt_dt_s); /** * Set specific fallback date/time to use when input is underspecified. * Internally, when no default is set and input is underspecified the * value of `dt_datetime()' (i.e. now) is used to fill fields up. * This is also used for ambiguous format specifiers (like %y or %_y) * to position their range on the absolute time scale. */ extern void dt_set_base(struct dt_dt_s); #define HAVE_DT_SET_BASE 1 /** * Return the base date/time as struct dt_dt_s. */ extern struct dt_dt_s dt_get_base(void); #define HAVE_DT_GET_BASE 1 /** * Crop datetimess with days beyond ultimo. */ extern __attribute__((pure)) struct dt_dt_s dt_fixup(struct dt_dt_s); /** * Decay military midnigths to the following day 00:00:00 */ extern __attribute__((pure)) struct dt_dt_s dt_milfup(struct dt_dt_s); /* some useful gimmicks, sort of */ static inline __attribute__((pure, const)) struct dt_dt_s dt_dt_initialiser(void) { #if defined HAVE_SLOPPY_STRUCTS_INIT static const struct dt_dt_s res = {}; #else static const struct dt_dt_s res; #endif /* HAVE_SLOPPY_STRUCTS_INIT */ return res; } static inline __attribute__((pure, const)) bool dt_unk_p(struct dt_dt_s d) { return !(d.sandwich || d.typ > DT_UNK); } static inline __attribute__((pure, const)) bool dt_durunk_p(struct dt_dtdur_s d) { return !d.durtyp; } static inline __attribute__((pure, const)) bool dt_sandwich_p(struct dt_dt_s d) { return d.sandwich && d.d.typ > DT_DUNK; } static inline __attribute__((pure, const)) bool dt_sandwich_only_d_p(struct dt_dt_s d) { return !d.sandwich && d.d.typ > DT_DUNK && d.d.typ < DT_NDTYP; } static inline __attribute__((pure, const)) bool dt_sandwich_only_t_p(struct dt_dt_s d) { return d.sandwich && d.typ == DT_UNK; } static inline __attribute__((pure, const)) bool dt_separable_p(struct dt_dt_s d) { /* return true if D is a d+t sandwich or D is d-only or D is t-only */ return d.typ < DT_PACK; } #define DT_SANDWICH_UNK (DT_UNK) static inline void dt_make_sandwich(struct dt_dt_s *d, dt_dtyp_t dty, dt_ttyp_t tty) { d->d.typ = dty; d->t.typ = tty; d->sandwich = 1; return; } static inline void dt_make_d_only(struct dt_dt_s *d, dt_dtyp_t dty) { d->d.typ = dty; d->t.typ = DT_TUNK; d->sandwich = 0; return; } static inline void dt_make_t_only(struct dt_dt_s *d, dt_ttyp_t tty) { d->d.typ = DT_DUNK; d->t.typ = tty; d->sandwich = 1; return; } #endif /* INCLUDED_dt_core_h_ */ dateutils-0.4.5/lib/dt-locale.c000066400000000000000000000315151335042257000163020ustar00rootroot00000000000000/*** locale.c -- locale light * * Copyright (C) 2015-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of dateutils. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***/ #if defined HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ /* for fgetln() */ #define _NETBSD_SOURCE #define _DARWIN_SOURCE #define _ALL_SOURCE #include #include #include #include #include #include #include #include #include #include "dt-locale.h" #include "date-core.h" #include "date-core-strpf.h" #include "nifty.h" #if defined LOCALE_FILE static const char locfn[] = LOCALE_FILE; #else /* !LOCALE_FILE */ static const char locfn[] = "locale"; #endif /* LOCALE_FILE */ #if !defined DEFUN # define DEFUN #endif /* !DEFUN */ #if !defined DEFVAR # define DEFVAR #endif /* !DEFVAR */ struct lst_s { const char *s[GREG_MONTHS_P_YEAR + 2U]; size_t min; size_t max; char str[]; }; struct loc_s { struct lst_s *long_wday; struct lst_s *abbr_wday; struct lst_s *long_mon; struct lst_s *abbr_mon; }; static const char *__long_wday[] = { "Miracleday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday", }; static const struct strprng_s __rlong_wday = {6, 9}; DEFVAR const char **dut_long_wday = __long_wday; DEFVAR const char **duf_long_wday = __long_wday; DEFVAR const ssize_t dut_nlong_wday = countof(__long_wday); DEFVAR struct strprng_s dut_rlong_wday = {6, 9}; static const char *__abbr_wday[] = { "Mir", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun", }; static const struct strprng_s __rabbr_wday = {3, 3}; DEFVAR const char **dut_abbr_wday = __abbr_wday; DEFVAR const char **duf_abbr_wday = __abbr_wday; DEFVAR const ssize_t dut_nabbr_wday = countof(__abbr_wday); DEFVAR struct strprng_s dut_rabbr_wday = {3, 3}; static const char __abab_wday[] = "XMTWRFAS"; DEFVAR const char *dut_abab_wday = __abab_wday; DEFVAR const ssize_t dut_nabab_wday = countof(__abab_wday); static const char *__long_mon[] = { "Miraculary", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December", }; static const struct strprng_s __rlong_mon = {3, 9}; DEFVAR const char **dut_long_mon = __long_mon; DEFVAR const char **duf_long_mon = __long_mon; DEFVAR const ssize_t dut_nlong_mon = countof(__long_mon); DEFVAR struct strprng_s dut_rlong_mon = {3, 9}; static const char *__abbr_mon[] = { "Mir", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", }; static const struct strprng_s __rabbr_mon = {3, 3}; DEFVAR const char **dut_abbr_mon = __abbr_mon; DEFVAR const char **duf_abbr_mon = __abbr_mon; DEFVAR const ssize_t dut_nabbr_mon = countof(__abbr_mon); DEFVAR struct strprng_s dut_rabbr_mon = {3, 3}; /* futures expiry codes, how convenient */ static const char __abab_mon[] = "_FGHJKMNQUVXZ"; DEFVAR const char *dut_abab_mon = __abab_mon; DEFVAR const ssize_t dut_nabab_mon = countof(__abab_mon); static inline __attribute__((unused)) void* deconst(const void *cp) { union { const void *c; void *p; } tmp = {cp}; return tmp.p; } static char* xmemmem(const char *hay, const size_t hayz, const char *ndl, const size_t ndlz) { const char *const eoh = hay + hayz; const char *const eon = ndl + ndlz; const char *hp; const char *np; const char *cand; unsigned int hsum; unsigned int nsum; unsigned int eqp; /* trivial checks first * a 0-sized needle is defined to be found anywhere in haystack * then run strchr() to find a candidate in HAYSTACK (i.e. a portion * that happens to begin with *NEEDLE) */ if (ndlz == 0UL) { return deconst(hay); } else if ((hay = memchr(hay, *ndl, hayz)) == NULL) { /* trivial */ return NULL; } /* First characters of haystack and needle are the same now. Both are * guaranteed to be at least one character long. Now computes the sum * of characters values of needle together with the sum of the first * needle_len characters of haystack. */ for (hp = hay + 1U, np = ndl + 1U, hsum = *hay, nsum = *hay, eqp = 1U; hp < eoh && np < eon; hsum ^= *hp, nsum ^= *np, eqp &= *hp == *np, hp++, np++); /* HP now references the (NZ + 1)-th character. */ if (np < eon) { /* haystack is smaller than needle, :O */ return NULL; } else if (eqp) { /* found a match */ return deconst(hay); } /* now loop through the rest of haystack, * updating the sum iteratively */ for (cand = hay; hp < eoh; hp++) { hsum ^= *cand++; hsum ^= *hp; /* Since the sum of the characters is already known to be * equal at that point, it is enough to check just NZ - 1 * characters for equality, * also CAND is by design < HP, so no need for range checks */ if (hsum == nsum && memcmp(cand, ndl, ndlz - 1U) == 0) { return deconst(cand); } } return NULL; } /* locale business */ static inline void __strp_reset_long_wday(void) { if (dut_long_wday != __long_wday) { free(deconst(dut_long_wday)); } dut_long_wday = __long_wday; dut_rlong_wday = __rlong_wday; return; } static inline void __strp_reset_abbr_wday(void) { if (dut_abbr_wday != __abbr_wday) { free(deconst(dut_abbr_wday)); } dut_abbr_wday = __abbr_wday; dut_rabbr_wday = __rabbr_wday; return; } static inline void __strp_reset_long_mon(void) { if (dut_long_mon != __long_mon) { free(deconst(dut_long_mon)); } dut_long_mon = __long_mon; dut_rlong_mon = __rlong_mon; return; } static inline void __strp_reset_abbr_mon(void) { if (dut_abbr_mon != __abbr_mon) { free(deconst(dut_abbr_mon)); } dut_abbr_mon = __abbr_mon; dut_rabbr_mon = __rabbr_mon; return; } static void __strp_set_long_wday(struct lst_s *new) { __strp_reset_long_wday(); dut_long_wday = new->s; dut_rlong_wday = (struct strprng_s){new->min, new->max}; return; } static void __strp_set_abbr_wday(struct lst_s *new) { __strp_reset_abbr_wday(); dut_abbr_wday = new->s; dut_rabbr_wday = (struct strprng_s){new->min, new->max}; return; } static void __strp_set_long_mon(struct lst_s *new) { __strp_reset_long_mon(); dut_long_mon = new->s; dut_rlong_mon = (struct strprng_s){new->min, new->max}; return; } static void __strp_set_abbr_mon(struct lst_s *new) { __strp_reset_abbr_mon(); dut_abbr_mon = new->s; dut_rabbr_mon = (struct strprng_s){new->min, new->max}; return; } static inline void __strf_reset_long_wday(void) { if (duf_long_wday != __long_wday) { free(deconst(duf_long_wday)); } duf_long_wday = __long_wday; return; } static inline void __strf_reset_abbr_wday(void) { if (duf_abbr_wday != __abbr_wday) { free(deconst(duf_abbr_wday)); } duf_abbr_wday = __abbr_wday; return; } static inline void __strf_reset_long_mon(void) { if (duf_long_mon != __long_mon) { free(deconst(duf_long_mon)); } duf_long_mon = __long_mon; return; } static inline void __strf_reset_abbr_mon(void) { if (dut_abbr_mon != __abbr_mon) { free(deconst(duf_abbr_mon)); } duf_abbr_mon = __abbr_mon; return; } static void __strf_set_long_wday(struct lst_s *new) { __strf_reset_long_wday(); duf_long_wday = new->s; return; } static void __strf_set_abbr_wday(struct lst_s *new) { __strp_reset_abbr_wday(); duf_abbr_wday = new->s; return; } static void __strf_set_long_mon(struct lst_s *new) { __strp_reset_long_mon(); duf_long_mon = new->s; return; } static void __strf_set_abbr_mon(struct lst_s *new) { __strp_reset_abbr_mon(); duf_abbr_mon = new->s; return; } static void reset_il(void) { __strp_reset_long_wday(); __strp_reset_abbr_wday(); __strp_reset_long_mon(); __strp_reset_abbr_mon(); return; } static void reset_fl(void) { __strf_reset_long_wday(); __strf_reset_abbr_wday(); __strf_reset_long_mon(); __strf_reset_abbr_mon(); return; } static void set_il(struct loc_s l) { __strp_set_long_wday(l.long_wday); __strp_set_abbr_wday(l.abbr_wday); __strp_set_long_mon(l.long_mon); __strp_set_abbr_mon(l.abbr_mon); return; } static void set_fl(struct loc_s l) { __strf_set_long_wday(l.long_wday); __strf_set_abbr_wday(l.abbr_wday); __strf_set_long_mon(l.long_mon); __strf_set_abbr_mon(l.abbr_mon); return; } static struct lst_s* tokenise(const char *ln, size_t lz) { /* we expect \t separation */ struct lst_s *r; if (UNLIKELY((r = malloc(sizeof(*r) + lz)) == NULL)) { return NULL; } /* just have him point to something */ r->s[1U] = r->str; r->min = -1ULL; r->max = 0ULL; memcpy(r->str, ln, lz); for (size_t i = 0U, j = 2U, o = 0U; i < lz && j < countof(r->s); i++) { /* just map all ascii ctrl characters to NUL */ r->str[i] &= (char)(((unsigned char)r->str[i] < ' ') - 1U); if (UNLIKELY(!r->str[i])) { const size_t len = i - o; r->s[j++] = r->str + (o = i + 1U); if (len > r->max) { r->max = len; } if (len < r->min) { r->min = len; } } } r->s[0U] = r->s[13U]; return r; } static int snarf_ln(struct loc_s *restrict tgt, const char *buf, size_t bsz) { const char *bp; const char *ep; struct lst_s *x; struct loc_s r; /* first one */ bp = buf; if (UNLIKELY(!(ep = memchr(bp, '\n', bsz - (bp - buf))))) { goto uhoh; } else if (UNLIKELY((x = tokenise(bp, ++ep - bp)) == NULL)) { goto uhoh; } /* got him */ r.abbr_wday = x; /* and again */ bp = ep; if (UNLIKELY(!(ep = memchr(bp, '\n', bsz - (bp - buf))))) { goto uhoh; } else if (UNLIKELY((x = tokenise(bp, ++ep - bp)) == NULL)) { goto uhoh; } /* got him */ r.long_wday = x; /* two to go */ bp = ep; if (UNLIKELY(!(ep = memchr(bp, '\n', bsz - (bp - buf))))) { goto uhoh; } else if (UNLIKELY((x = tokenise(bp, ++ep - bp)) == NULL)) { goto uhoh; } /* got him */ r.abbr_mon = x; /* just one more */ bp = ep; if (UNLIKELY(!(ep = memchr(bp, '\n', bsz - (bp - buf))))) { goto uhoh; } else if (UNLIKELY((x = tokenise(bp, ++ep - bp)) == NULL)) { goto uhoh; } /* got him */ r.long_mon = x; *tgt = r; return 0; uhoh: if (r.long_wday) { free(r.long_wday); } if (r.abbr_wday) { free(r.abbr_wday); } if (r.long_mon) { free(r.long_mon); } if (r.abbr_mon) { free(r.abbr_mon); } return -1; } static int __setlocale(const char *ln, size_t lz, void(*setf)(struct loc_s)) { struct stat st[1U]; const char *fn; ssize_t fz; int fd; int rc = 0; /* we shall assume locale file is LOCALE_FILE */ fn = getenv("LOCALE_FILE") ?: locfn; if ((fd = open(fn, O_RDONLY)) < 0) { /* buggery */ return -1; } else if (UNLIKELY(fstat(fd, st) < 0)) { /* knew it! */ rc = -1; goto clo; } else if (UNLIKELY((fz = st->st_size) <= 0)) { /* it's not our lucky day today */ rc = -1; goto clo; } /* map him entirely */ with (const char *m = mmap(NULL, fz, PROT_READ, MAP_SHARED, fd, 0)) { const char *l; struct loc_s loc; if (UNLIKELY(m == MAP_FAILED)) { /* good one */ rc = -1; goto clo; } /* none of the locales should be a prefix to another */ if (UNLIKELY((l = xmemmem(m, fz, ln, lz)) == NULL)) { ; } else if (UNLIKELY(l[lz++] != '\n')) { ; } else if (snarf_ln(&loc, l + lz, fz - (l + lz - m)) < 0) { /* ... so we've found the one match * but reading the locale lines went pearshaped */ ; } else { /* finally set them */ setf(loc); } munmap(deconst(m), fz); } clo: close(fd); return rc; } int setilocale(const char *ln) { size_t lz; if (UNLIKELY(ln == NULL || !(lz = strlen(ln)))) { reset_il(); return 0; } return __setlocale(ln, lz, set_il); } int setflocale(const char *ln) { size_t lz; if (UNLIKELY(ln == NULL || !(lz = strlen(ln)))) { reset_fl(); return 0; } return __setlocale(ln, lz, set_fl); } /* locale.c ends here */ dateutils-0.4.5/lib/dt-locale.h000066400000000000000000000067071335042257000163140ustar00rootroot00000000000000/*** locale.h -- locale light * * Copyright (C) 2015-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of dateutils. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***/ #if !defined INCLUDED_dt_locale_h_ #define INCLUDED_dt_locale_h_ /* textual representations of parts of the date */ /** * Long weekday names, english only. * Monday, Tuesday, ... * The duf_* version is for the formatters. */ extern const char **dut_long_wday; extern const char **duf_long_wday; extern const ssize_t dut_nlong_wday; extern struct strprng_s dut_rlong_wday; /** * Abbrev'd weekday names, english only. * Mon, Tue, ... * The duf_* version is for the formatters */ extern const char **dut_abbr_wday; extern const char **duf_abbr_wday; extern const ssize_t dut_nabbr_wday; extern struct strprng_s dut_rabbr_wday; /** * Even-more-abbrev'd weekday names, english only. * M, T, W, ... * There is no distinction between input and output formats. */ extern const char *dut_abab_wday; extern const ssize_t dut_nabab_wday; /** * Long month names, english only. * January, February, ... * The duf_* version is for the formatters. */ extern const char **dut_long_mon; extern const char **duf_long_mon; extern const ssize_t dut_nlong_mon; extern struct strprng_s dut_rlong_mon; /** * Abbrev'd month names, english only. * Jan, Feb, ... * The duf_* version is for the formatters. */ extern const char **dut_abbr_mon; extern const char **duf_abbr_mon; extern const ssize_t dut_nabbr_mon; extern struct strprng_s dut_rabbr_mon; /** * Even-more-abbrev'd month names. * F, G, H, ... * There is no distinction between input and output formats. */ extern const char *dut_abab_mon; extern const ssize_t dut_nabab_mon; /* public API */ /** * Set input locale (only LC_TIME values) to LOCALE. * Just as stupid as setlocale(3). */ extern int setilocale(const char *locale); /** * Set formatting locale (only LC_TIME values) to LOCALE. * Just as stupid as setlocale(3). */ extern int setflocale(const char *locale); #endif /* INCLUDED_dt_locale_h_ */ dateutils-0.4.5/lib/fmt-special.gperf000066400000000000000000000010561335042257000175200ustar00rootroot00000000000000%{ #if !defined DT_SEXY_BASE_YEAR # define DT_SEXY DT_DUNK #endif /* !DT_SEXY_BASE_YEAR */ %} %7bit %readonly-tables %switch=1 %ignore-case %enum %struct-type %define slot-name special %define hash-function-name ____fmt_special %define lookup-function-name __fmt_special %null-strings struct dt_fmt_special_s { const char *special; dt_dtyp_t e; }; %% ymd, DT_YMD ymcw, DT_YMCW bizda, DT_BIZDA daisy, DT_DAISY sexy, (dt_dtyp_t)DT_SEXY bizsi, DT_BIZSI ywd, DT_YWD yd, DT_YD julian, DT_JDN jdn, DT_JDN lilian, DT_LDN ldn, DT_LDN matlab, DT_MDN mdn, DT_MDN dateutils-0.4.5/lib/generics.h000066400000000000000000000050201335042257000162320ustar00rootroot00000000000000/*** generics.h -- type invariant generic funs * * Copyright (C) 2012-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of dateutils. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***/ #if !defined INCLUDED_generics_h_ #define INCLUDED_generics_h_ #if defined HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #if defined __cplusplus extern "C" { #endif /* __cplusplus */ /** * Compare two dates, yielding 0 if they are equal, -1 if D1 is older, * 1 if D1 is younger than the D2. */ #define dt_cmp(d1, d2) \ _Generic((d1), \ struct dt_d_s: dt_dcmp, \ struct dt_t_s: dt_tcmp, \ struct dt_dt_s: dt_dtcmp, \ default: NULL \ )(d1, d2) /** * Check if D is in the interval spanned by D1 and D2, * 1 if D1 is younger than the D2. */ #define dt_in_range_p(d, d1, d2) \ _Generic((d1), \ struct dt_d_s: dt_d_in_range_p, \ struct dt_t_s: dt_t_in_range_p, \ struct dt_dt_s: dt_dt_in_range_p, \ default: NULL \ )(d, d1, d2) #if defined __cplusplus } #endif /* __cplusplus */ #endif /* INCLUDED_generics_h_ */ dateutils-0.4.5/lib/gmtime.h000066400000000000000000000045131335042257000157230ustar00rootroot00000000000000/* metaprogramming */ #if !defined INCLUDED_gmtime_h_ #define INCLUDED_gmtime_h_ #include /* UTC has a constant day length */ #define UTC_SECS_PER_DAY (86400) static void ffff_gmtime(struct tm *tm, const time_t t) { static uint16_t __mon_yday[] = { /* this is \sum ml, * first element is a bit set of leap days to add */ 0xfff8, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; register int days; register unsigned int yy; const uint16_t *ip; #if defined FFFF_GMTIME_SUBDAY int secs; #endif /* FFFF_GMTIME_SUBDAY */ /* just go to day computation */ days = (int)(t / UTC_SECS_PER_DAY); #if defined FFFF_GMTIME_SUBDAY secs = (int)(t % UTC_SECS_PER_DAY); #endif /* FFFF_GMTIME_SUBDAY */ /* week day computation, that one's easy, 1 jan '70 was Thu */ tm->tm_wday = (days + 4) % GREG_DAYS_P_WEEK; /* gotta do the date now */ yy = 1970; /* stolen from libc */ #define DIV(a, b) ((a) / (b)) /* we only care about 1901 to 2099 and there are no bullshit leap years */ #define LEAPS_TILL(y) (DIV(y, 4)) while (days < 0 || days >= (!__leapp(yy) ? 365 : 366)) { /* Guess a corrected year, assuming 365 days per year. */ register unsigned int yg = yy + days / 365 - (days % 365 < 0); /* Adjust DAYS and Y to match the guessed year. */ days -= (yg - yy) * 365 + LEAPS_TILL(yg - 1) - LEAPS_TILL(yy - 1); yy = yg; } /* set the year */ tm->tm_year = (int)yy; ip = __mon_yday; /* unrolled */ yy = 13; if (days < ip[--yy] && days < ip[--yy] && days < ip[--yy] && days < ip[--yy] && days < ip[--yy] && days < ip[--yy] && days < ip[--yy] && days < ip[--yy] && days < ip[--yy] && days < ip[--yy] && days < ip[--yy]) { yy = 1; } /* set the rest of the tm structure */ tm->tm_mday = days - ip[yy] + 1; tm->tm_yday = days; tm->tm_mon = (int)yy; /* fix up leap years */ if (UNLIKELY(__leapp(tm->tm_year))) { if ((ip[0] >> (yy)) & 1) { if (UNLIKELY(tm->tm_yday == 59)) { tm->tm_mon = 2; tm->tm_mday = 29; } else if (UNLIKELY(tm->tm_yday == ip[yy])) { tm->tm_mday = tm->tm_yday - ip[--tm->tm_mon]; } else { tm->tm_mday--; } } } #if defined FFFF_GMTIME_SUBDAY tm->tm_sec = secs % 60U; secs /= 60U; tm->tm_min = secs % 60U; secs /= 60U; tm->tm_hour = secs; #endif /* FFFF_GMTIME_SUBDAY */ return; } #endif /* INCLUDED_gmtime_h_ */ dateutils-0.4.5/lib/iata.tzminfo000066400000000000000000000007431335042257000166170ustar00rootroot00000000000000- Domain: IATA 3-letter airport codes - Author: [Sebastian Freundt][1] - Source: [The GeoNames geographical database][2] - Licence: [Creative Commons Attribution 3.0 License][3] This list maps airports by their IATA 3-letter airport code to the local IANA timezone. It is generally assumed that the airport in question indeed operates in local time. [1]: http://www.fresse.org/ [2]: http://download.geonames.org/export/dump/ [3]: http://creativecommons.org/licenses/by/3.0/ dateutils-0.4.5/lib/icao.tzminfo000066400000000000000000000007431335042257000166140ustar00rootroot00000000000000- Domain: ICAO 4-letter airport codes - Author: [Sebastian Freundt][1] - Source: [The GeoNames geographical database][2] - Licence: [Creative Commons Attribution 3.0 License][3] This list maps airports by their ICAO 4-letter airport code to the local IANA timezone. It is generally assumed that the airport in question indeed operates in local time. [1]: http://www.fresse.org/ [2]: http://download.geonames.org/export/dump/ [3]: http://creativecommons.org/licenses/by/3.0/ dateutils-0.4.5/lib/leap-seconds.h000066400000000000000000000014101335042257000170070ustar00rootroot00000000000000/*** header counterpart to auto-gen'd leapseconds.def */ #if !defined INCLUDED_leap_seconds_h_ #define INCLUDED_leap_seconds_h_ #include /** * Number of known leap corrections. */ extern const size_t nleaps; /** * Absolute difference in seconds, TAI - UTC, at transition points */ extern const int32_t leaps_corr[]; /** * YMD representation of transitions. */ extern const uint32_t leaps_ymd[]; /** * YMCW representation of transitions. */ extern const uint32_t leaps_ymcw[]; /** * daisy representation of transitions. */ extern const uint32_t leaps_d[]; /** * sexy representation of transitions. */ extern const int32_t leaps_s[]; /** * HMS representation of transitions. */ extern const uint32_t leaps_hms[]; #endif /* INCLUDED_leap_seconds_h_ */ dateutils-0.4.5/lib/leap-seconds.list000066400000000000000000000246521335042257000175500ustar00rootroot00000000000000# # In the following text, the symbol '#' introduces # a comment, which continues from that symbol until # the end of the line. A plain comment line has a # whitespace character following the comment indicator. # There are also special comment lines defined below. # A special comment will always have a non-whitespace # character in column 2. # # A blank line should be ignored. # # The following table shows the corrections that must # be applied to compute International Atomic Time (TAI) # from the Coordinated Universal Time (UTC) values that # are transmitted by almost all time services. # # The first column shows an epoch as a number of seconds # since 1 January 1900, 00:00:00 (1900.0 is also used to # indicate the same epoch.) Both of these time stamp formats # ignore the complexities of the time scales that were # used before the current definition of UTC at the start # of 1972. (See note 3 below.) # The second column shows the number of seconds that # must be added to UTC to compute TAI for any timestamp # at or after that epoch. The value on each line is # valid from the indicated initial instant until the # epoch given on the next one or indefinitely into the # future if there is no next line. # (The comment on each line shows the representation of # the corresponding initial epoch in the usual # day-month-year format. The epoch always begins at # 00:00:00 UTC on the indicated day. See Note 5 below.) # # Important notes: # # 1. Coordinated Universal Time (UTC) is often referred to # as Greenwich Mean Time (GMT). The GMT time scale is no # longer used, and the use of GMT to designate UTC is # discouraged. # # 2. The UTC time scale is realized by many national # laboratories and timing centers. Each laboratory # identifies its realization with its name: Thus # UTC(NIST), UTC(USNO), etc. The differences among # these different realizations are typically on the # order of a few nanoseconds (i.e., 0.000 000 00x s) # and can be ignored for many purposes. These differences # are tabulated in Circular T, which is published monthly # by the International Bureau of Weights and Measures # (BIPM). See www.bipm.org for more information. # # 3. The current definition of the relationship between UTC # and TAI dates from 1 January 1972. A number of different # time scales were in use before that epoch, and it can be # quite difficult to compute precise timestamps and time # intervals in those "prehistoric" days. For more information, # consult: # # The Explanatory Supplement to the Astronomical # Ephemeris. # or # Terry Quinn, "The BIPM and the Accurate Measurement # of Time," Proc. of the IEEE, Vol. 79, pp. 894-905, # July, 1991. # reprinted in: # Christine Hackman and Donald B Sullivan (eds.) # Time and Frequency Measurement # American Association of Physics Teachers (1996) # , pp. 75-86 # # 4. The decision to insert a leap second into UTC is currently # the responsibility of the International Earth Rotation and # Reference Systems Service. (The name was changed from the # International Earth Rotation Service, but the acronym IERS # is still used.) # # Leap seconds are announced by the IERS in its Bulletin C. # # See www.iers.org for more details. # # Every national laboratory and timing center uses the # data from the BIPM and the IERS to construct UTC(lab), # their local realization of UTC. # # Although the definition also includes the possibility # of dropping seconds ("negative" leap seconds), this has # never been done and is unlikely to be necessary in the # foreseeable future. # # 5. If your system keeps time as the number of seconds since # some epoch (e.g., NTP timestamps), then the algorithm for # assigning a UTC time stamp to an event that happens during a positive # leap second is not well defined. The official name of that leap # second is 23:59:60, but there is no way of representing that time # in these systems. # Many systems of this type effectively stop the system clock for # one second during the leap second and use a time that is equivalent # to 23:59:59 UTC twice. For these systems, the corresponding TAI # timestamp would be obtained by advancing to the next entry in the # following table when the time equivalent to 23:59:59 UTC # is used for the second time. Thus the leap second which # occurred on 30 June 1972 at 23:59:59 UTC would have TAI # timestamps computed as follows: # # ... # 30 June 1972 23:59:59 (2287785599, first time): TAI= UTC + 10 seconds # 30 June 1972 23:59:60 (2287785599,second time): TAI= UTC + 11 seconds # 1 July 1972 00:00:00 (2287785600) TAI= UTC + 11 seconds # ... # # If your system realizes the leap second by repeating 00:00:00 UTC twice # (this is possible but not usual), then the advance to the next entry # in the table must occur the second time that a time equivalent to # 00:00:00 UTC is used. Thus, using the same example as above: # # ... # 30 June 1972 23:59:59 (2287785599): TAI= UTC + 10 seconds # 30 June 1972 23:59:60 (2287785600, first time): TAI= UTC + 10 seconds # 1 July 1972 00:00:00 (2287785600,second time): TAI= UTC + 11 seconds # ... # # in both cases the use of timestamps based on TAI produces a smooth # time scale with no discontinuity in the time interval. However, # although the long-term behavior of the time scale is correct in both # methods, the second method is technically not correct because it adds # the extra second to the wrong day. # # This complexity would not be needed for negative leap seconds (if they # are ever used). The UTC time would skip 23:59:59 and advance from # 23:59:58 to 00:00:00 in that case. The TAI offset would decrease by # 1 second at the same instant. This is a much easier situation to deal # with, since the difficulty of unambiguously representing the epoch # during the leap second does not arise. # # Some systems implement leap seconds by amortizing the leap second # over the last few minutes of the day. The frequency of the local # clock is decreased (or increased) to realize the positive (or # negative) leap second. This method removes the time step described # above. Although the long-term behavior of the time scale is correct # in this case, this method introduces an error during the adjustment # period both in time and in frequency with respect to the official # definition of UTC. # # Questions or comments to: # Judah Levine # Time and Frequency Division # NIST # Boulder, Colorado # Judah.Levine@nist.gov # # Last Update of leap second values: 8 July 2016 # # The following line shows this last update date in NTP timestamp # format. This is the date on which the most recent change to # the leap second data was added to the file. This line can # be identified by the unique pair of characters in the first two # columns as shown below. # #$ 3676924800 # # The NTP timestamps are in units of seconds since the NTP epoch, # which is 1 January 1900, 00:00:00. The Modified Julian Day number # corresponding to the NTP time stamp, X, can be computed as # # X/86400 + 15020 # # where the first term converts seconds to days and the second # term adds the MJD corresponding to the time origin defined above. # The integer portion of the result is the integer MJD for that # day, and any remainder is the time of day, expressed as the # fraction of the day since 0 hours UTC. The conversion from day # fraction to seconds or to hours, minutes, and seconds may involve # rounding or truncation, depending on the method used in the # computation. # # The data in this file will be updated periodically as new leap # seconds are announced. In addition to being entered on the line # above, the update time (in NTP format) will be added to the basic # file name leap-seconds to form the name leap-seconds.. # In addition, the generic name leap-seconds.list will always point to # the most recent version of the file. # # This update procedure will be performed only when a new leap second # is announced. # # The following entry specifies the expiration date of the data # in this file in units of seconds since the origin at the instant # 1 January 1900, 00:00:00. This expiration date will be changed # at least twice per year whether or not a new leap second is # announced. These semi-annual changes will be made no later # than 1 June and 1 December of each year to indicate what # action (if any) is to be taken on 30 June and 31 December, # respectively. (These are the customary effective dates for new # leap seconds.) This expiration date will be identified by a # unique pair of characters in columns 1 and 2 as shown below. # In the unlikely event that a leap second is announced with an # effective date other than 30 June or 31 December, then this # file will be edited to include that leap second as soon as it is # announced or at least one month before the effective date # (whichever is later). # If an announcement by the IERS specifies that no leap second is # scheduled, then only the expiration date of the file will # be advanced to show that the information in the file is still # current -- the update time stamp, the data and the name of the file # will not change. # # Updated through IERS Bulletin C55 # File expires on: 28 December 2018 # #@ 3754944000 # 2272060800 10 # 1 Jan 1972 2287785600 11 # 1 Jul 1972 2303683200 12 # 1 Jan 1973 2335219200 13 # 1 Jan 1974 2366755200 14 # 1 Jan 1975 2398291200 15 # 1 Jan 1976 2429913600 16 # 1 Jan 1977 2461449600 17 # 1 Jan 1978 2492985600 18 # 1 Jan 1979 2524521600 19 # 1 Jan 1980 2571782400 20 # 1 Jul 1981 2603318400 21 # 1 Jul 1982 2634854400 22 # 1 Jul 1983 2698012800 23 # 1 Jul 1985 2776982400 24 # 1 Jan 1988 2840140800 25 # 1 Jan 1990 2871676800 26 # 1 Jan 1991 2918937600 27 # 1 Jul 1992 2950473600 28 # 1 Jul 1993 2982009600 29 # 1 Jul 1994 3029443200 30 # 1 Jan 1996 3076704000 31 # 1 Jul 1997 3124137600 32 # 1 Jan 1999 3345062400 33 # 1 Jan 2006 3439756800 34 # 1 Jan 2009 3550089600 35 # 1 Jul 2012 3644697600 36 # 1 Jul 2015 3692217600 37 # 1 Jan 2017 # # the following special comment contains the # hash value of the data in this file computed # use the secure hash algorithm as specified # by FIPS 180-1. See the files in ~/pub/sha for # the details of how this hash value is # computed. Note that the hash computation # ignores comments and whitespace characters # in data lines. It includes the NTP values # of both the last modification time and the # expiration time of the file, but not the # white space on those lines. # the hash line is also ignored in the # computation. # #h 44dcf58c e28d25aa b36612c8 f3d3e8b5 a8fdf478 dateutils-0.4.5/lib/leaps.c000066400000000000000000000072531335042257000155440ustar00rootroot00000000000000/*** leaps.c -- materialised leap seconds * * Copyright (C) 2012-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of dateutils. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***/ /* implementation part of leaps.h */ #if !defined INCLUDED_leaps_c_ #define INCLUDED_leaps_c_ #if defined HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include #include #include "nifty.h" #include "leaps.h" typedef ssize_t sidx_t; #if !defined DEFUN # define DEFUN #endif /* !DEFUN */ /* this can be called roughly 100m/sec */ #define DEF_FIND_BEFORE(N, X) \ static zidx_t \ find_before_##N( \ const X v[], size_t nv, X key, zidx_t i, zidx_t min, zidx_t max) \ { \ /* Given key K find the index of the transition before */ \ do { \ X lo, up; \ \ lo = v[i]; \ up = v[i + 1]; \ \ if (key > lo && key <= up) { \ /* found him */ \ break; \ } else if (key > up) { \ min = i + 1; \ i = (i + max) / 2; \ } else if (key <= lo) { \ max = i - 1; \ i = (i + min) / 2; \ } \ } while (max > min && i < nv); \ return i; \ } \ static const int UNUSED(defined_find_before_##name##_p) DEF_FIND_BEFORE(ui32, uint32_t); DEF_FIND_BEFORE(si32, int32_t); DEF_FIND_BEFORE(ui64, uint64_t); DEF_FIND_BEFORE(si64, int64_t); /* public apis */ DEFUN zidx_t leaps_before_ui32(const uint32_t fld[], size_t nfld, uint32_t key) { zidx_t min = 0; zidx_t max = nfld - 1; zidx_t this = max / 2; return find_before_ui32(fld, nfld, key, this, min, max); } DEFUN zidx_t leaps_before_si32(const int32_t fld[], size_t nfld, int32_t key) { zidx_t min = 0; zidx_t max = nfld - 1; zidx_t this = max / 2; return find_before_si32(fld, nfld, key, this, min, max); } DEFUN zidx_t leaps_before_ui64(const uint64_t fld[], size_t nfld, uint64_t key) { zidx_t min = 0; zidx_t max = nfld - 1; zidx_t this = max / 2; return find_before_ui64(fld, nfld, key, this, min, max); } DEFUN zidx_t leaps_before_si64(const int64_t fld[], size_t nfld, int64_t key) { zidx_t min = 0; zidx_t max = nfld - 1; zidx_t this = max / 2; return find_before_si64(fld, nfld, key, this, min, max); } #endif /* INCLUDED_leaps_c_ */ /* leaps.c ends here */ dateutils-0.4.5/lib/leaps.h000066400000000000000000000052641335042257000155510ustar00rootroot00000000000000/*** leaps.h -- materialised leap seconds * * Copyright (C) 2012-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of dateutils. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***/ #if !defined INCLUDED_leaps_h_ #define INCLUDED_leaps_h_ #include #include #if defined __cplusplus extern "C" { #endif /* __cplusplus */ typedef const struct zleap_s *zleap_t; typedef const int32_t *zltr_t; typedef size_t zidx_t; /* row-based */ struct zleap_s { union { uint32_t u; int32_t v; }; int32_t corr; }; /* col-based funs */ /** * Return last leap transition before KEY in a uint32_t field FLD. */ extern zidx_t leaps_before_ui32(const uint32_t fld[], size_t nfld, uint32_t key); /** * Return last leap transition before KEY in a int32_t field FLD. */ extern zidx_t leaps_before_si32(const int32_t fld[], size_t nfld, int32_t key); /** * Return last leap transition before KEY in a uint64_t field FLD. */ extern zidx_t leaps_before_ui64(const uint64_t fld[], size_t nfld, uint64_t key); /** * Return last leap transition before KEY in a int64_t field FLD. */ extern zidx_t leaps_before_si64(const int64_t fld[], size_t nfld, int64_t key); #if defined __cplusplus } #endif /* __cplusplus */ #endif /* INCLUDED_leaps_h_ */ dateutils-0.4.5/lib/ltrcc.c000066400000000000000000000220321335042257000155370ustar00rootroot00000000000000/*** ltrcc.c -- leapseconds materialiser * * Copyright (C) 2012-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of dateutils. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***/ #if defined HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include #include #include #if defined HAVE_SYS_STDINT_H # include #endif /* HAVE_SYS_STDINT_H */ #include #include #include #include "leaps.h" #include "date-core.h" #include "time-core.h" #include "nifty.h" #include "version.c" static __attribute__((pure, const)) long int ntp_to_unix_epoch(long int x) { return x - 25567L * 86400L; } #define PROLOGUE (-1UL) #define EPILOGUE (0UL) static int pr_line_corr(const char *line, size_t llen, va_list UNUSED(vap)) { static long int cor; char *sp, *ep; if (llen == PROLOGUE) { /* prologue */ fprintf(stdout, "\ const int32_t %s[] = {\n\ 10,\n", line); return 0; } else if (llen == EPILOGUE) { fprintf(stdout, "\ %ld\n\ };\n", cor); cor = 0; return 0; } else if (line == NULL) { /* grrrr */ return -1; } else if (line[0] == '#') { /* comment line */ return 0; } else if (line[0] == '\n') { /* empty line */ return 0; } /* otherwise process */ if ((sp = memchr(line, '\t', llen)) == NULL) { return -1; } else if ((ep = NULL, cor = strtol(++sp, &ep, 10), ep == NULL)) { return -1; } /* output the correction then */ fprintf(stdout, "\t%ld,\n", cor); return 0; } static int pr_line_d(const char *line, size_t llen, va_list vap) { static long int cor; struct dt_d_s d; dt_dtyp_t typ; long int val; int colp; char *ep; /* extract type from inner list */ typ = va_arg(vap, dt_dtyp_t); colp = va_arg(vap, int); if (llen == PROLOGUE) { /* prologue */ if (!colp) { fprintf(stdout, "\ const struct zleap_s %s[] = {\n\ {0x00U/* 0 */, 0},\n", line); } else { fprintf(stdout, "\ const uint32_t %s[] = {\n\ 0x00U/* 0 */,\n", line); } return 0; } else if (llen == EPILOGUE) { /* epilogue */ if (!colp) { fprintf(stdout, "\ {UINT32_MAX, %li}\n\ };\n", cor); } else { fputs("\ UINT32_MAX\n\ };\n", stdout); } cor = 0; return 0; } else if (line == NULL) { /* something's fucked */ return -1; } else if (line[0] == '#') { /* comment line */ return 0; } else if (line[0] == '\n') { /* empty line */ return 0; } /* otherwise process */ if ((ep = NULL, val = strtol(line, &ep, 10), ep == NULL)) { return -1; } /* fix up and convert to target type */ d = (struct dt_d_s){DT_DAISY, .daisy = val / 86400 + 109207}; d = dt_dconv(typ, d); if (!colp) { if ((cor = strtol(ep, &ep, 10), ep == NULL)) { return -1; } /* just output the line then */ fprintf(stdout, "\t{0x%xU/* %i */, %li},\n", d.u, (int32_t)d.u, cor); } else { fprintf(stdout, "\t0x%xU/* %i */,\n", d.u, (int32_t)d.u); } return 0; } static int pr_line_dt(const char *line, size_t llen, va_list vap) { static long int cor; dt_dtyp_t __attribute__((unused)) typ; long int val; int colp; char *ep; /* extract type from inner list */ typ = va_arg(vap, dt_dtyp_t); colp = va_arg(vap, int); if (llen == PROLOGUE) { /* prologue */ if (!colp) { fprintf(stdout, "\ const struct zleap_s %s[] = {\n\ {INT32_MIN, 10},\n", line); } else { fprintf(stdout, "\ const int32_t %s[] = {\n\ INT32_MIN,\n", line); } return 0; } else if (llen == EPILOGUE) { /* epilogue */ if (!colp) { fprintf(stdout, "\ {INT32_MAX, %li}\n\ };\n", cor); } else { fputs("\ INT32_MAX\n\ };\n", stdout); } cor = 0; return 0; } else if (line == NULL) { /* buggre */ return -1; } else if (line[0] == '#') { /* comment line */ return 0; } else if (line[0] == '\n') { /* empty line */ return 0; } /* otherwise process */ if ((ep = NULL, val = strtol(line, &ep, 10), ep == NULL)) { return -1; } /* fix up and convert to target type */ val--; val = ntp_to_unix_epoch(val); if (!colp) { if ((cor = strtol(ep, &ep, 10), ep == NULL)) { return -1; } /* just output the line then */ fprintf(stdout, "\t{0x%xU/* %li */, %li},\n", (uint32_t)val, val, cor); } else { /* column-oriented mode */ fprintf(stdout, "\t0x%xU/* %li */,\n", (uint32_t)val, val); } return 0; } static int pr_line_t(const char *line, size_t llen, va_list vap) { static long int cor; struct dt_t_s t = dt_t_initialiser(); dt_dtyp_t typ; int colp; char *ep; long int val; /* extract type from inner list */ typ = va_arg(vap, dt_dtyp_t); colp = va_arg(vap, int); /* column-oriented mode only */ if (!colp) { return 0; } if (llen == PROLOGUE) { /* prologue */ fprintf(stdout, "\ const uint32_t %s[] = {\n\ UINT32_MAX,\n", line); return 0; } else if (llen == EPILOGUE) { /* epilogue */ fputs("\ UINT32_MAX\n\ };\n", stdout); cor = 0; return 0; } else if (typ != (dt_dtyp_t)DT_HMS || !colp) { return 0; } else if (line == NULL) { /* do fuckall */ return -1; } else if (line[0] == '#') { /* comment line */ return 0; } else if (line[0] == '\n') { /* empty line */ return 0; } /* otherwise process */ if ((ep = NULL, val = strtol(line, &ep, 10), ep == NULL)) { return -1; } val--; t.hms.s = val % 60L; val /= 60L; t.hms.m = val % 60L; val /= 60L; t.hms.h = val % 24L; /* read correction */ if ((val = strtol(ep, &ep, 10), ep == NULL)) { return -1; } /* fix up and convert to target type */ with (uint32_t ual = t.hms.u24) { ual += val >= cor; fprintf(stdout, "\t0x%xU/* %u */,\n", ual, ual); cor = val; } return 0; } static int pr_file(FILE *fp, const char *var, int(*cb)(const char*, size_t, va_list), ...) { va_list vap; char *line = NULL; size_t len = 0; ssize_t nrd; /* prologue */ va_start(vap, cb); cb(var, PROLOGUE, vap); va_end(vap); /* main loop */ while ((nrd = getline(&line, &len, fp)) >= 0) { va_start(vap, cb); if (cb(line, nrd, vap) < 0) { fprintf(stderr, "line buggered: %s", line); } va_end(vap); } /* epilogue */ va_start(vap, cb); cb(var, EPILOGUE, vap); va_end(vap); /* standard epilogue */ fprintf(stdout, "\ const size_t n%s = countof(%s);\n\n", var, var); if (line != NULL) { free(line); } return 0; } static int col = 0; static int parse_file(const char *file) { FILE *fp; if ((fp = fopen(file, "r")) == NULL) { return -1; } fprintf(stdout, "\ /*** autogenerated by: ltrcc %s */\n\ \n\ #include \n\ #include \n\ #include \"leaps.h\"\n\ #include \"leap-seconds.h\"\n\ \n\ #if !defined INCLUDED_ltrcc_generated_def_\n\ #define INCLUDED_ltrcc_generated_def_\n\ \n\ #if !defined countof\n\ # define countof(x) (sizeof(x) / sizeof(*x))\n\ #endif /* !countof */\n\ \n", file); if (col) { pr_file(fp, "leaps_corr", pr_line_corr); rewind(fp); } pr_file(fp, "leaps_ymd", pr_line_d, DT_YMD, col); rewind(fp); pr_file(fp, "leaps_ymcw", pr_line_d, DT_YMCW, col); rewind(fp); pr_file(fp, "leaps_d", pr_line_d, DT_DAISY, col); rewind(fp); pr_file(fp, "leaps_s", pr_line_dt, DT_YMD, col); rewind(fp); pr_file(fp, "leaps_hms", pr_line_t, DT_HMS, col); fputs("\ /* exported number of leap transitions */\n\ const size_t nleaps = countof(leaps_corr);\n\ \n\ #endif /* INCLUDED_ltrcc_generated_def_ */\n", stdout); return 0; } #include "ltrcc.yucc" int main(int argc, char *argv[]) { yuck_t argi[1U]; int rc = 0; if (yuck_parse(argi, argc, argv) < 0) { rc = 1; goto out; } else if (!argi->nargs) { fputs("LEAP-SECONDSS.LIST argument is mandatory\n", stderr); rc = 1; goto out; } /* assign params */ col = argi->column_oriented_flag; if (parse_file(argi->args[0U]) < 0) { perror("Cannot parse file"); rc = 1; } out: yuck_free(argi); return rc; } /* ltrcc.c ends here */ dateutils-0.4.5/lib/ltrcc.yuck000066400000000000000000000002101335042257000162620ustar00rootroot00000000000000Usage: ltrcc LEAP-SECONDS.LIST Compile LEAP-SECONDS.LIST into C source code. -C, --column-oriented Produce column-oriented output. dateutils-0.4.5/lib/mic.tzminfo000066400000000000000000000010251335042257000164430ustar00rootroot00000000000000- Domain: ISO-10383 4-letter Market Identifier Codes - Author: [Sebastian Freundt][1] - Source: [Codes for exchanges and market identification][2] - Licence: [Creative Commons Attribution 3.0 License][3] This list maps market codes to their IANA timezones based on a market's official trading hours and report times. I.e. the mapping does not necessarily reflect where the market is headquartered. [1]: http://www.fresse.org/ [2]: http://www.iso15022.org/MIC/homepageMIC.htm [3]: http://creativecommons.org/licenses/by/3.0/ dateutils-0.4.5/lib/nifty.h000066400000000000000000000044141335042257000155720ustar00rootroot00000000000000/*** nifty.h -- generally handy macroes * * Copyright (C) 2009-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of dateutils. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***/ #if !defined INCLUDED_nifty_h_ #define INCLUDED_nifty_h_ #if !defined LIKELY # define LIKELY(_x) __builtin_expect((_x), 1) #endif /* !LIKELY */ #if !defined UNLIKELY # define UNLIKELY(_x) __builtin_expect((_x), 0) #endif /* UNLIKELY */ #if !defined UNUSED # define UNUSED(_x) _x __attribute__((unused)) #endif /* !UNUSED */ #if !defined ALGN # define ALGN(_x, to) _x __attribute__((aligned(to))) #endif /* !ALGN */ #if !defined countof # define countof(x) (sizeof(x) / sizeof(*x)) #endif /* !countof */ #if !defined with # define with(args...) for (args, *__ep__ = (void*)1; __ep__; __ep__ = 0) #endif /* !with */ #endif /* INCLUDED_nifty_h_ */ dateutils-0.4.5/lib/strops.c000066400000000000000000000237251335042257000157740ustar00rootroot00000000000000/*** strops.c -- useful string operations * * Copyright (C) 2011-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of dateutils. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * **/ /* implementation part of strops.h */ #if !defined INCLUDED_strops_c_ #define INCLUDED_strops_c_ #if defined HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include #include /* for strncasecmp() */ #include #include #if defined HAVE_SYS_STDINT_H # include #endif /* HAVE_SYS_STDINT_H */ #include "nifty.h" #include "strops.h" #if defined __INTEL_COMPILER /* we MUST return a char* */ # pragma warning (disable:2203) #elif defined __GNUC__ # pragma GCC diagnostic ignored "-Wcast-qual" #endif /* __INTEL_COMPILER */ #if !defined DEFUN # define DEFUN #endif /* DEFUN */ /* stolen from Klaus Klein/David Laight's strptime() */ DEFUN int32_t strtoi_lim(const char *str, const char **ep, int32_t llim, int32_t ulim) { const char *sp = str; int32_t res = 0; /* we keep track of the number of digits via rulim */ for (int32_t rulim = ulim > 10 ? ulim : 10; rulim && (unsigned char)(*sp ^ '0') < 10U && (res *= 10, res += (unsigned char)(*sp++ ^ '0')) <= ulim; rulim /= 10); if (UNLIKELY(sp == str)) { res = -1; } else if (UNLIKELY(res < llim || res > ulim)) { res = -2; } *ep = (char*)sp; return res; } DEFUN int32_t padstrtoi_lim(const char *str, const char **ep, int32_t llim, int32_t ulim) { const char *sp; int32_t rulim = ulim > 10 ? ulim : 10; int32_t res = 0; /* overread whitespace */ for (; *str == ' '; str++, rulim /= 10); /* we keep track of the number of digits via rulim */ for (sp = str; rulim && (unsigned char)(*sp ^ '0') < 10U && (res *= 10, res += (unsigned char)(*sp++ ^ '0')) <= ulim; rulim /= 10); if (UNLIKELY(sp == str)) { res = -1; } else if (UNLIKELY(res < llim || res > ulim)) { res = -2; } *ep = (char*)sp; return res; } DEFUN int32_t strtoi(const char *str, const char **ep) { const char *sp = str; bool negp = false; int32_t res = 0; if (*str == '-') { negp = true; sp++; } while (res < INT32_MAX / 10 && (unsigned char)(*sp ^ '0') < 10U) { res *= 10, res += (unsigned char)(*sp++ ^ '0'); } if (UNLIKELY(sp == str)) { res = -1; } else if (negp) { res = -res; } *ep = (char*)sp; return res; } /* roman numerals */ static int32_t __romstr_v(const char c) { switch (c) { case 'n': case 'N': return 0; case 'i': case 'I': return 1; case 'v': case 'V': return 5; case 'x': case 'X': return 10; case 'l': case 'L': return 50; case 'c': case 'C': return 100; case 'd': case 'D': return 500; case 'm': case 'M': return 1000; default: return -1; } } DEFUN int32_t romstrtoi_lim(const char *str, const char **ep, int32_t llim, int32_t ulim) { int32_t res = 0; const char *sp; int32_t v; /* loops through characters */ for (sp = str, v = __romstr_v(*sp); *sp; sp++) { int32_t nv = __romstr_v(sp[1]); if (UNLIKELY(v < 0)) { break; } else if (LIKELY(nv < 0 || v >= nv)) { res += v; } else { res -= v; } v = nv; } if (UNLIKELY(sp == str)) { res = -1; } else if (UNLIKELY(res < llim || res > ulim)) { res = -2; } *ep = (char*)sp; return res; } static size_t __rom_pr1(char *buf, size_t bsz, unsigned int i, char cnt, char hi, char lo) { size_t res = 0; if (UNLIKELY(bsz < 4)) { return 0; } switch (i) { case 9: buf[res++] = cnt; buf[res++] = hi; break; case 4: buf[res++] = cnt; buf[res++] = lo; break; case 8: buf[++res] = cnt; case 7: buf[++res] = cnt; case 6: buf[++res] = cnt; case 5: buf[0] = lo; res++; break; case 3: buf[res++] = cnt; case 2: buf[res++] = cnt; case 1: buf[res++] = cnt; break; default: buf[res] = '\0'; break; } return res; } DEFUN size_t ui32tostrrom(char *restrict buf, size_t bsz, uint32_t d) { size_t res; for (res = 0; d >= 1000 && res < bsz; d -= 1000) { buf[res++] = 'M'; } res += __rom_pr1(buf + res, bsz - res, d / 100U, 'C', 'M', 'D'); d %= 100; res += __rom_pr1(buf + res, bsz - res, d / 10U, 'X', 'C', 'L'); d %= 10; res += __rom_pr1(buf + res, bsz - res, d, 'I', 'X', 'V'); return res; } DEFUN int __ordinalp(const char *num, size_t off_suf, char **ep) { #define __tolower(c) (c | 0x20) #define ILEA(a, b) (((a) << 8) | (b)) const char *p = num + off_suf; int res = 0; int p2; if (UNLIKELY(off_suf == 0 || p[0] == '\0')) { res = -1; goto yep; } else if ((p2 = ILEA(__tolower(p[0]), __tolower(p[1]))), LIKELY(p2 == ILEA('t', 'h'))) { /* we accept 1th 2th 3th */ p += 2; goto yep; } else if (UNLIKELY(off_suf >= 2 && p[-2] == '1')) { res = -1; goto yep; } /* irregular ordinals */ switch (p[-1]) { case '1': if (p2 == ILEA('s', 't')) { p += 2; } break; case '2': if (p2 == ILEA('n', 'd')) { p += 2; } break; case '3': if (p2 == ILEA('r', 'd')) { p += 2; } break; default: res = -1; break; } yep: *ep = (char*)p; return res; #undef ILEA #undef __tolower } DEFUN size_t __ordtostr(char *buf, size_t bsz) { char *p = buf; if (UNLIKELY(bsz < 2)) { return 0; } /* assumes the actual number is printed in BUF already, 2 digits long */ if (UNLIKELY(p[-2] == '1')) { /* must be 11, 12, or 13 then */ goto teens; } else if (p[-2] == '0') { /* discard */ p[-2] = p[-1]; p--; } switch (p[-1]) { default: teens: *p++ = 't'; *p++ = 'h'; break; case '1': *p++ = 's'; *p++ = 't'; break; case '2': *p++ = 'n'; *p++ = 'd'; break; case '3': *p++ = 'r'; *p++ = 'd'; break; } return p - buf; } /* string array funs */ DEFUN int32_t strtoarri(const char *buf, const char **ep, const char *const *arr, size_t narr) { /* take a string, compare it to an array of string (case-insensitively) and * return its index if found or 0 if not */ for (size_t i = 1U; i < narr; i++) { const char *chk = arr[i]; size_t len = strlen(chk); if (strncasecmp(chk, buf, len) == 0) { if (ep != NULL) { *ep = buf + len; } return i; } } /* no matches */ if (ep != NULL) { *ep = buf; } return -1; } DEFUN size_t arritostr( char *restrict buf, size_t bsz, size_t i, const char *const *arr, size_t narr) { /* take a string array, an index into the array and print the string * behind it into BUF, return the number of bytes copied */ size_t ncp; size_t len; if (i > narr) { return 0; } len = strlen(arr[i]); ncp = bsz > len ? len : bsz; memcpy(buf, arr[i], ncp); return ncp; } /* faster strpbrk, strspn and strcspn, code by Richard A. O'Keefe * comp.unix.programmer Message-ID: <5449jv$p21$1@goanna.cs.rmit.edu.au>#1/1 */ #define ALPHABET_SIZE (256) /* not reentrant */ static unsigned char table[ALPHABET_SIZE]; static unsigned char cycle = 0; static inline bool in_current_set(unsigned char c) { return table[c] == cycle; } static inline void set_up_table(const unsigned char *set, bool include_NUL) { if (LIKELY(set != NULL)) { /* useful for strtok() too */ if (UNLIKELY(cycle == ALPHABET_SIZE - 1)) { memset(table, 0, sizeof(table)); cycle = (unsigned char)1; } else { cycle = (unsigned char)(cycle + 1); } while (*set) { table[*set++] = cycle; } } table[0] = (unsigned char)(include_NUL ? cycle : 0); return; } DEFUN size_t xstrspn(const char *src, const char *set) { size_t i; set_up_table((const unsigned char*)set, false); for (i = 0; in_current_set((unsigned char)src[i]); i++); return i; } DEFUN size_t xstrcspn(const char *src, const char *set) { size_t i; set_up_table((const unsigned char*)set, true); for (i = 0; !in_current_set((unsigned char)src[i]); i++); return i; } DEFUN char* xstrpbrk(const char *src, const char *set) { const char *p; set_up_table((const unsigned char*)set, true); for (p = src; !in_current_set((unsigned char)*p); p++); return (char*)p; } DEFUN char* xstrpbrkp(const char *src, const char *set, size_t *set_offs) { const char *p; set_up_table((const unsigned char*)set, true); for (p = src; !in_current_set((unsigned char)*p); p++); if (LIKELY(set_offs != NULL)) { size_t idx; for (idx = 0; set[idx] != *p; idx++); *set_offs = idx; } return (char*)p; } DEFUN char* xmempbrk(const char *src, size_t len, const char *set) { size_t i; set_up_table((const unsigned char*)set, false); for (i = 0U; i < len && !in_current_set((unsigned char)src[i]); i++); return (char*)src + i; } #if defined __INTEL_COMPILER # pragma warning (default:2203) #elif defined __GNUC__ # pragma GCC diagnostic warning "-Wcast-qual" #endif /* __INTEL_COMPILER */ #endif /* INCLUDED_strops_c_ */ dateutils-0.4.5/lib/strops.h000066400000000000000000000153561335042257000160020ustar00rootroot00000000000000/*** strops.h -- useful string operations * * Copyright (C) 2011-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of dateutils. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * **/ #if !defined INCLUDED_strops_h_ #define INCLUDED_strops_h_ #include #include /* stolen from Klaus Klein/David Laight's strptime() */ /** * Convert STR to i32 and point to the end of the string in EP. */ extern __attribute__((nonnull(1, 2))) int32_t strtoi_lim(const char *str, const char **ep, int32_t llim, int32_t ulim); /** * Convert possibly padded STR to i32 and point to the end in EP. */ extern __attribute__((nonnull(1, 2))) int32_t padstrtoi_lim(const char *str, const char **ep, int32_t llim, int32_t ulim); /** * Convert STR to i32 and point to the end of the string in EP. */ extern __attribute__((nonnull(1, 2))) int32_t strtoi(const char *str, const char **ep); /** * Convert roman numeral (string) to i32 and point to its end in EP. */ extern int32_t romstrtoi_lim(const char *str, const char **ep, int32_t llim, int32_t ulim); /** * Convert D to a roman numeral string and put it into BUF, return the size. */ extern size_t ui32tostrrom(char *restrict buf, size_t bsz, uint32_t d); /** * Find and skip ordinal suffixes in SUF, point to the end of the suffix. */ extern int __ordinalp(const char *num, size_t off_suf, char **ep); /** * Append ordinal suffix to the most recently printed number in BUF, * eating away a leading 0. */ extern size_t __ordtostr(char *buf, size_t bsz); /** * Take a string S, (case-insensitively) compare it to an array of strings ARR * of size NARR and return its index if found or -1 if not. * If S could be found in the array, point to the end of the string S in EP. * The 0-th index will not be checked. */ extern int32_t strtoarri(const char *s, const char **ep, const char *const *arr, size_t narr); /** * Take a string array ARR (of size NARR) and an index I into the array, print * the string ARR[I] into BUF and return the number of bytes copied. */ extern size_t arritostr( char *restrict buf, size_t bsz, size_t i, const char *const *arr, size_t narr); /** * Faster strspn(). */ extern size_t xstrspn(const char *src, const char *set); /** * Faster strcspn(). */ extern size_t xstrcspn(const char *src, const char *set); /** * Faster strpbrk(). */ extern char* xstrpbrk(const char *src, const char *set); /** * Like xstrpbrk() but also return the offset to the character in set * that caused the match. */ extern char* xstrpbrkp(const char *src, const char *set, size_t *set_offs); /** * Like strpbrk() but consider a string of length LEN. */ extern char* xmempbrk(const char *src, size_t len, const char *set); static inline char ui2c(uint32_t x, char pad) { return (char)((pad > 0 || x > 0) << 5U | ((x > 0) << 4U) | (x ^ pad)); } static inline size_t ui99topstr(char *restrict b, size_t z, uint32_t d, size_t width, char pad) { /* specifically for numbers 00-99, signature like ui32topstr() */ if (z) { uint32_t d10 = d / 10U, drem = d % 10U; size_t i; i = 0U; b[i] = ui2c(d10, pad); i += (d10 > 0U || width > 1U && pad) && z > 1U; b[i++] = ui2c(drem, '0'); return i; } return 0U; } static inline size_t ui999topstr(char *restrict b, size_t z, uint32_t d, size_t width, char pad) { /* specifically for numbers 000-999, signature like ui32topstr() */ if (z) { uint32_t d100 = d / 100U, drem = d % 100U; size_t i; i = 0U; b[i] = ui2c(d100, pad); i += (d100 > 0U || width > 2U && pad) && z > 2U; d100 = drem / 10U, drem = drem % 10U; b[i] = ui2c(d100, pad); i += (d100 > 0U || width > 1U && pad) && z > 1U; b[i++] = ui2c(drem, '0'); return i; } return 0U; } static inline size_t ui9999topstr(char *restrict b, size_t z, uint32_t d, size_t width, char pad) { /* specifically for numbers 0000-9999, signature like ui32topstr() */ if (z) { uint32_t d1000 = d / 1000U, drem = d % 1000U; size_t i; i = 0U; b[i] = ui2c(d1000, pad); i += (d1000 > 0U || width > 3U && pad) && z > 3U; d1000 = drem / 100U, drem = drem % 100U; b[i] = ui2c(d1000, pad); i += (d1000 > 0U || width > 2U && pad) && z > 2U; d1000 = drem / 10U, drem = drem % 10U; b[i] = ui2c(d1000, pad); i += (d1000 > 0U || width > 1U && pad) && z > 1U; b[i++] = ui2c(drem, '0'); return i; } return 0U; } static inline size_t ui999999999tostr(char *restrict b, size_t z, uint32_t d) { /* specifically for nanoseconds, this one fills the buffer from * most significant to least significant */ if (z) { uint32_t dx = d / 100000000U, dr = d % 100000000U; size_t i = 0U; b[i++] = ui2c(dx, '0'); if (!--z) { return i; } dx = dr / 10000000U, dr = dr % 10000000U; b[i++] = ui2c(dx, '0'); if (!--z) { return i; } dx = dr / 1000000U, dr = dr % 1000000U; b[i++] = ui2c(dx, '0'); if (!--z) { return i; } dx = dr / 100000U, dr = dr % 100000U; b[i++] = ui2c(dx, '0'); if (!--z) { return i; } dx = dr / 10000U, dr = dr % 10000U; b[i++] = ui2c(dx, '0'); if (!--z) { return i; } dx = dr / 1000U, dr = dr % 1000U; b[i++] = ui2c(dx, '0'); if (!--z) { return i; } dx = dr / 100U, dr = dr % 100U; b[i++] = ui2c(dx, '0'); if (!--z) { return i; } dx = dr / 10U, dr = dr % 10U; b[i++] = ui2c(dx, '0'); if (!--z) { return i; } b[i++] = ui2c(dr, '0'); return i; } return 0U; } #endif /* INCLUDED_strops_h_ */ dateutils-0.4.5/lib/testlib.c000066400000000000000000000025731335042257000161060ustar00rootroot00000000000000/* library tester */ #include #include #include #include "date-core.h" static const char test_ymd[] = "2001-02-03"; static const char test_ybd[] = "2001-Feb-03"; static void __attribute__((unused)) orig_strptime_perf(size_t nruns) { for (size_t i = 0; i < nruns; i++) { struct tm tm; strptime(test_ymd, "%Y-%m-%d", &tm); } return; } static void __attribute__((unused)) test_strpd(size_t nruns) { struct dt_d_s s; for (size_t i = 0; i < nruns; i++) { if ((s = dt_strpd(test_ymd, "%F", NULL)).u == 0) { break; } } if ((s = dt_strpd(test_ymd, "%F", NULL)).typ) { char buf[256]; dt_strfd(buf, sizeof(buf), "%F %a %A %b %B\n", s); fputs(buf, stdout); } if ((s = dt_strpd(test_ybd, "%Y-%b-%d", NULL)).typ) { char buf[256]; dt_strfd(buf, sizeof(buf), "%F %a %A %b %B\n", s); fputs(buf, stdout); } return; } static void __attribute__((unused)) test_date(size_t nruns) { struct dt_d_s s = {{0}}; char buf[256]; for (size_t i = 0; i < nruns; i++) { if ((s = dt_date(DT_YMCW)).u == 0) { break; } } dt_strfd(buf, sizeof(buf), "%Y-%m-%c-%w\n", s); fputs(buf, stdout); return; } int main(int argc __attribute__((unused)), char *argv[] __attribute__((unused))) { const size_t nruns = 10000000; #if 0 orig_strptime_perf(nruns); #elif 0 test_strpd(nruns); #elif 1 test_date(nruns); #endif return 0; } /* testlib.c ends here */ dateutils-0.4.5/lib/time-core-private.h000066400000000000000000000036461335042257000200030ustar00rootroot00000000000000/*** time-core-private.h -- our universe of times, private bits * * Copyright (C) 2011-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of dateutils. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * **/ /* private portion of time-core.h */ #if !defined INCLUDED_time_core_private_h_ #define INCLUDED_time_core_private_h_ /* formatting defaults */ extern const char hms_dflt[]; extern dt_ttyp_t __trans_tfmt(const char **fmt); #endif /* INCLUDED_time_core_private_h_ */ dateutils-0.4.5/lib/time-core-strpf.c000066400000000000000000000141011335042257000174460ustar00rootroot00000000000000/*** time-core-strpf.c -- parser and formatter funs for time-core * * Copyright (C) 2011-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of dateutils. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * **/ /* implementation part of time-core-strpf.h */ #if !defined INCLUDED_time_core_strpf_c_ #define INCLUDED_time_core_strpf_c_ #if defined HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include "strops.h" #include "token.h" #include "time-core.h" #include "time-core-strpf.h" #if !defined DEFUN # define DEFUN #endif /* !DEFUN */ #if defined __INTEL_COMPILER /* we MUST return a char* */ # pragma warning (disable:2203) #elif defined __GNUC__ # pragma GCC diagnostic ignored "-Wcast-qual" #endif /* __INTEL_COMPILER */ DEFUN int __strpt_card(struct strpt_s *d, const char *str, struct dt_spec_s s, char **ep) { const char *sp = str; switch (s.spfl) { default: case DT_SPFL_UNK: goto fucked; case DT_SPFL_N_TSTD: if ((d->h = strtoi_lim(sp, &sp, 0, 23)) < 0 || *sp++ != ':') { goto fucked; } else if ((d->m = strtoi_lim(sp, &sp, 0, 59)) < 0 || *sp++ != ':') { goto fucked; } else if ((d->s = strtoi_lim(sp, &sp, 0, 60)) < 0) { goto fucked; } break; case DT_SPFL_N_HOUR: if (!s.sc12) { d->h = strtoi_lim(sp, &sp, 0, 23); } else { d->h = strtoi_lim(sp, &sp, 1, 12); } if (d->h < 0) { goto fucked; } break; case DT_SPFL_N_MIN: if ((d->m = strtoi_lim(sp, &sp, 0, 59)) < 0) { goto fucked; } break; case DT_SPFL_N_SEC: if ((d->s = strtoi_lim(sp, &sp, 0, 60)) < 0) { goto fucked; } break; case DT_SPFL_N_NANO: { /* nanoseconds */ const char *on; if ((d->ns = strtoi_lim(sp, &on, 0, 999999999)) < 0) { goto fucked; } switch (on - sp) { case 0: goto fucked; case 1: d->ns *= 10; case 2: d->ns *= 10; case 3: d->ns *= 10; case 4: d->ns *= 10; case 5: d->ns *= 10; case 6: d->ns *= 10; case 7: d->ns *= 10; case 8: d->ns *= 10; default: case 9: break; } sp = on; break; } case DT_SPFL_S_AMPM: { const unsigned int casebit = 0x20; d->flags.am_pm_bit = 1; if ((sp[0] | casebit) == 'a' && (sp[1] | casebit) == 'm') { d->flags.pm_p = 0; } else if ((sp[0] | casebit) == 'p' && (sp[1] | casebit) == 'm') { d->flags.pm_p = 1; } else { goto fucked; } sp += 2; break; } case DT_SPFL_LIT_PERCENT: if (*sp++ != '%') { goto fucked; } break; case DT_SPFL_LIT_TAB: if (*sp++ != '\t') { goto fucked; } break; case DT_SPFL_LIT_NL: if (*sp++ != '\n') { goto fucked; } break; } /* check if components got set */ switch (s.spfl) { case DT_SPFL_N_TSTD: d->flags.h_set = 1; d->flags.m_set = 1; d->flags.s_set = 1; break; case DT_SPFL_N_HOUR: d->flags.h_set = 1; break; case DT_SPFL_N_MIN: d->flags.m_set = 1; break; case DT_SPFL_N_SEC: d->flags.s_set = 1; break; case DT_SPFL_N_NANO: d->flags.ns_set = 1; break; default: break; } /* assign end pointer */ if (ep != NULL) { *ep = (char*)sp; } return 0; fucked: if (ep != NULL) { *ep = (char*)str; } return -1; } DEFUN size_t __strft_card( char *buf, size_t bsz, struct dt_spec_s s, struct strpt_s *d, struct dt_t_s UNUSED(that)) { size_t res = 0; switch (s.spfl) { default: case DT_SPFL_UNK: break; case DT_SPFL_N_TSTD: if (LIKELY(bsz >= 8)) { ui99topstr(buf + 0, bsz, d->h, 2, '0'); buf[2] = ':'; ui99topstr(buf + 3, bsz, d->m, 2, '0'); buf[5] = ':'; ui99topstr(buf + 6, bsz, d->s, 2, '0'); res = 8; } break; case DT_SPFL_N_HOUR: if (!s.sc12 || (d->h >= 1 && d->h <= 12)) { res = ui99topstr( buf, bsz, d->h, 2 - (s.pad == DT_SPPAD_OMIT), padchar(s)); } else { unsigned int h = d->h ? d->h - 12 : 12; res = ui99topstr( buf, bsz, h, 2 - (s.pad == DT_SPPAD_OMIT), padchar(s)); } break; case DT_SPFL_N_MIN: res = ui99topstr( buf, bsz, d->m, 2 - (s.pad == DT_SPPAD_OMIT), padchar(s)); break; case DT_SPFL_N_SEC: res = ui99topstr( buf, bsz, d->s, 2 - (s.pad == DT_SPPAD_OMIT), padchar(s)); break; case DT_SPFL_S_AMPM: { unsigned int casebit = 0; if (UNLIKELY(!s.cap)) { casebit = 0x20; } if (d->h >= 12 && d->h < 24) { buf[res++] = (char)('P' | casebit); } else { buf[res++] = (char)('A' | casebit); } buf[res++] = (char)('M' | casebit); break; } case DT_SPFL_N_NANO: res = ui999999999tostr(buf, bsz, d->ns); break; case DT_SPFL_LIT_PERCENT: /* literal % */ buf[res++] = '%'; break; case DT_SPFL_LIT_TAB: /* literal tab */ buf[res++] = '\t'; break; case DT_SPFL_LIT_NL: /* literal \n */ buf[res++] = '\n'; break; } return res; } #endif /* INCLUDED_time_core_strpf_c_ */ dateutils-0.4.5/lib/time-core-strpf.h000066400000000000000000000054341335042257000174640ustar00rootroot00000000000000/*** time-core-strpf.h -- parser and formatter funs for time-core * * Copyright (C) 2011-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of dateutils. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * **/ #if !defined INCLUDED_time_core_strpf_h_ #define INCLUDED_time_core_strpf_h_ #if defined __cplusplus extern "C" { #endif /* __cplusplus */ struct strpt_s { signed int h; signed int m; signed int s; signed int ns; union { unsigned int u; struct { /* whether am/pm indicator was given */ unsigned int am_pm_bit:1; /* 0 for am, 1 for pm */ unsigned int pm_p:1; unsigned int h_set:1; unsigned int m_set:1; unsigned int s_set:1; unsigned int ns_set:1; }; } flags; }; extern struct dt_t_s __guess_ttyp(struct strpt_s t); /* helpers */ static inline __attribute__((pure, const)) struct strpt_s strpt_initialiser(void) { #if defined HAVE_SLOPPY_STRUCTS_INIT static const struct strpt_s res = {}; #else static const struct strpt_s res; #endif /* HAVE_SLOPPY_STRUCTS_INIT */ return res; } /* self-explanatory funs */ extern int __strpt_card(struct strpt_s *d, const char *str, struct dt_spec_s s, char **ep); extern size_t __strft_card( char *buf, size_t bsz, struct dt_spec_s s, struct strpt_s *d, struct dt_t_s that); #if defined __cplusplus } #endif /* __cplusplus */ #endif /* INCLUDED_time_core_strpf_h_ */ dateutils-0.4.5/lib/time-core.c000066400000000000000000000156301335042257000163220ustar00rootroot00000000000000/*** time-core.c -- our universe of times * * Copyright (C) 2011-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of dateutils. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * **/ /* implementation part of time-core.h */ #if !defined INCLUDED_time_core_c_ #define INCLUDED_time_core_c_ #if defined HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include "time-core.h" #include "time-core-private.h" #include "nifty.h" #if !defined DEFUN # define DEFUN #endif /* !DEFUN */ #if !defined DEFVAR # define DEFVAR #endif /* !DEFVAR */ #if defined __INTEL_COMPILER /* we MUST return a char* */ # pragma warning (disable:2203) #elif defined __GNUC__ # pragma GCC diagnostic ignored "-Wcast-qual" #endif /* __INTEL_COMPILER */ /* guessing parsers */ #include "strops.h" #include "token.h" #include "time-core-strpf.c" DEFVAR const char hms_dflt[] = "%H:%M:%S"; DEFUN struct dt_t_s __guess_ttyp(struct strpt_s t) { struct dt_t_s res; if (UNLIKELY(!(t.flags.h_set || t.flags.m_set || t.flags.s_set || t.flags.ns_set))) { goto fucked; } if (UNLIKELY(t.h < 0)) { goto fucked; } if (UNLIKELY(t.m < 0)) { goto fucked; } if (UNLIKELY(t.s < 0)) { goto fucked; } if (UNLIKELY(t.ns < 0)) { goto fucked; } res.typ = DT_HMS; res.neg = 0; res.hms.s = t.s; res.hms.m = t.m; res.hms.h = t.h; res.hms.ns = t.ns; if (t.flags.am_pm_bit) { /* pm */ res.hms.h %= HOURS_PER_DAY / 2U; res.hms.h += t.flags.pm_p ? 12U : 0U; } return res; fucked: return dt_t_initialiser(); } DEFUN dt_ttyp_t __trans_tfmt(const char **fmt) { if (UNLIKELY(*fmt == NULL)) { /* don't worry about it */ *fmt = hms_dflt; } else if (LIKELY(**fmt == '%')) { /* don't worry about it */ ; } else if (strcasecmp(*fmt, "hms") == 0) { *fmt = hms_dflt; return DT_HMS; } return DT_TUNK; } /* parser implementations */ DEFUN struct dt_t_s dt_strpt(const char *str, const char *fmt, char **ep) { struct dt_t_s res = dt_t_initialiser(); struct strpt_s d = strpt_initialiser(); const char *sp = str; const char *fp; /* translate high-level format names */ __trans_tfmt(&fmt); fp = fmt; while (*fp && *sp) { const char *fp_sav = fp; struct dt_spec_s spec = __tok_spec(fp_sav, &fp); if (spec.spfl == DT_SPFL_UNK) { /* must be literal */ if (*fp_sav != *sp++) { sp = str; goto out; } } else if (__strpt_card(&d, sp, spec, (char**)&sp) < 0) { sp = str; goto out; } } /* set the end pointer */ res = __guess_ttyp(d); out: if (ep != NULL) { *ep = (char*)sp; } return res; } DEFUN size_t dt_strft(char *restrict buf, size_t bsz, const char *fmt, struct dt_t_s that) { struct strpt_s d; const char *fp; char *bp; if (UNLIKELY(buf == NULL || bsz == 0)) { return 0; } d = strpt_initialiser(); d.h = that.hms.h; d.m = that.hms.m; d.s = that.hms.s; d.ns = that.hms.ns; if (fmt == NULL) { fmt = hms_dflt; } /* translate high-level format names */ __trans_tfmt(&fmt); /* assign and go */ bp = buf; fp = fmt; for (char *const eo = buf + bsz; *fp && bp < eo;) { const char *fp_sav = fp; struct dt_spec_s spec = __tok_spec(fp_sav, &fp); if (spec.spfl == DT_SPFL_UNK) { /* must be literal then */ *bp++ = *fp_sav; } else { bp += __strft_card(bp, eo - bp, spec, &d, that); } } if (bp < buf + bsz) { *bp = '\0'; } return bp - buf; } /* arithmetics helpers */ struct divrem_s { signed int div; unsigned int rem; }; static struct divrem_s divrem(signed int n, unsigned int mod) { register signed int _div; register signed int _rem; _div = n / (signed int)mod; if ((_rem = n % (signed int)mod) < 0) { _div--; _rem += mod; } return (struct divrem_s){_div, (unsigned int)_rem}; } DEFUN struct dt_t_s dt_tadd_s(struct dt_t_s t, int durs, int corr) { struct divrem_s tmp; signed int sec; /* get both result in seconds since midnight */ sec = (t.hms.h * MINS_PER_HOUR + t.hms.m) * SECS_PER_MIN + t.hms.s; sec += durs; /* doesn't work if we span more than 2 days */ tmp = divrem(sec, SECS_PER_DAY + corr); /* fill up biggest first */ if (LIKELY(tmp.rem < SECS_PER_DAY)) { t.hms.h = tmp.rem / SECS_PER_HOUR; tmp.rem %= SECS_PER_HOUR; t.hms.m = tmp.rem / SECS_PER_MIN; tmp.rem %= SECS_PER_MIN; t.hms.s = tmp.rem; } else { /* leap-second day case * corr < 0 will always end up in the above case */ t.hms.h = 23; t.hms.m = 59; t.hms.s = 59 + corr; } /* set up the return type */ t.typ = DT_HMS; t.neg = 0; t.carry = tmp.div; return t; } DEFUN int dt_tdiff_s(struct dt_t_s t1, struct dt_t_s t2) { /* compute t2 - t1 */ int r = 0; r += (t2.hms.h - t1.hms.h) * SECS_PER_HOUR; r += (t2.hms.m - t1.hms.m) * SECS_PER_MIN; r += (t2.hms.s - t1.hms.s); return r; } DEFUN int dt_tcmp(struct dt_t_s t1, struct dt_t_s t2) { if (t1.u < t2.u) { return -1; } else if (t1.u > t2.u) { return 1; } else { return 0; } } DEFUN struct dt_t_s dt_time(void) { struct dt_t_s res = {0}; struct timeval tv; unsigned int tonly; if (gettimeofday(&tv, NULL) < 0) { return res; } tonly = tv.tv_sec % 86400U; res.hms.h = tonly / SECS_PER_HOUR; tonly %= SECS_PER_HOUR; res.hms.m = tonly / SECS_PER_MIN; tonly %= SECS_PER_MIN; res.hms.s = tonly; res.hms.ns = tv.tv_usec * 1000; return res; } #if defined __INTEL_COMPILER # pragma warning (default:2203) #elif defined __GNUC__ # pragma GCC diagnostic warning "-Wcast-qual" #endif /* __INTEL_COMPILER */ #endif /* INCLUDED_time_core_c_ */ /* time-core.c ends here */ dateutils-0.4.5/lib/time-core.h000066400000000000000000000124221335042257000163230ustar00rootroot00000000000000/*** time-core.h -- our universe of times * * Copyright (C) 2011-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of dateutils. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * **/ #if !defined INCLUDED_time_core_h_ #define INCLUDED_time_core_h_ #include #include #include #include "boops.h" #include "token.h" #if defined __cplusplus extern "C" { #endif /* __cplusplus */ typedef enum { DT_TUNK, #define DT_TUNK (dt_ttyp_t)(DT_TUNK) DT_HMS, #define DT_HMS (dt_ttyp_t)(DT_HMS) DT_NTTYP, } dt_ttyp_t; /** hms * hms times are just bog-standard hour, minute, second times */ typedef union { uint64_t u:56; struct { #if BYTE_ORDER == BIG_ENDIAN uint32_t u24:24; uint32_t:32; #elif BYTE_ORDER == LITTLE_ENDIAN uint32_t:32; uint32_t u24:24; #else # warning unknown byte order #endif /* BYTE_ORDER */ } __attribute__((packed)); struct { #if BYTE_ORDER == BIG_ENDIAN uint64_t h:8; uint64_t m:8; uint64_t s:8; uint64_t ns:32; #elif BYTE_ORDER == LITTLE_ENDIAN uint64_t ns:32; uint64_t s:8; uint64_t m:8; uint64_t h:8; #else # warning unknown byte order #endif /* BYTE_ORDER */ } __attribute__((packed)); } __attribute__((packed)) dt_hms_t; /** * Collection of all time types. */ struct dt_t_s { struct { dt_ttyp_t typ:2; uint64_t dur:1; uint64_t neg:1; /* used for tadd operations and whatnot, range [-7,7] */ int64_t carry:4; } __attribute__((packed)); union { uint64_t u:56; struct { signed int sdur; unsigned int nsdur:10; } __attribute__((packed)); dt_hms_t hms; } __attribute__((packed)); }; /* helpers */ #if !defined NANOS_PER_SEC # define NANOS_PER_SEC (1000U * 1000U * 1000U) #endif /* !SECS_PER_MIN */ #if !defined SECS_PER_MIN # define SECS_PER_MIN (60U) #endif /* !SECS_PER_MIN */ #if !defined MINS_PER_HOUR # define MINS_PER_HOUR (60U) #endif /* !MINS_PER_HOUR */ #if !defined HOURS_PER_DAY # define HOURS_PER_DAY (24U) #endif /* !HOURS_PER_DAY */ #if !defined SECS_PER_HOUR # define SECS_PER_HOUR (SECS_PER_MIN * MINS_PER_HOUR) #endif /* !SECS_PER_HOUR */ #if !defined SECS_PER_DAY # define SECS_PER_DAY (SECS_PER_HOUR * HOURS_PER_DAY) #endif /* !SECS_PER_DAY */ /* decls */ /** * Like strptime() for our times. * The format characters are _NOT_ compatible with strptime(). * If FMT is NULL the standard format for each calendric system is used, * see format.texi or dateutils info page. * * If optional EP is non-NULL it will point to the end of the parsed * date string. */ extern struct dt_t_s dt_strpt(const char *str, const char *fmt, char **ep); /** * Like strftime() for our times. */ extern size_t dt_strft(char *restrict buf, size_t bsz, const char *fmt, struct dt_t_s); /** * Add DURS seconds and CORR corrections to T. */ extern struct dt_t_s dt_tadd_s(struct dt_t_s t, int durs, int corr); /** * Compute the duration between T1 and T2 (as in T2 - T1). */ extern int dt_tdiff_s(struct dt_t_s t1, struct dt_t_s t2); /** * Compare two time values, yielding 0 if they are equal, -1 if T1 is older, * 1 if T1 is younger than the T2. */ extern int dt_tcmp(struct dt_t_s t1, struct dt_t_s t2); /** * Like time() but always return the current UTC time. */ extern struct dt_t_s dt_time(void); #if defined LIBDUT /** * Return the base date/time as struct dt_t_s. * Defined in dt-core.c */ extern struct dt_t_s dt_get_tbase(void); #endif /* LIBDUT */ /* some useful gimmicks, sort of */ static inline __attribute__((pure, const)) struct dt_t_s dt_t_initialiser(void) { #if defined HAVE_SLOPPY_STRUCTS_INIT static const struct dt_t_s res = {}; #else static const struct dt_t_s res; #endif /* HAVE_SLOPPY_STRUCTS_INIT */ return res; } static inline unsigned int __secs_since_midnight(struct dt_t_s t) { return (t.hms.h * MINS_PER_HOUR + t.hms.m) * SECS_PER_MIN + t.hms.s; } #if defined __cplusplus } #endif /* __cplusplus */ #endif /* INCLUDED_time_core_h_ */ dateutils-0.4.5/lib/token.c000066400000000000000000000122241335042257000155520ustar00rootroot00000000000000/*** token.c -- tokeniser specs and stuff * * Copyright (C) 2011-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of dateutils. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * **/ /* implementation part of token.h */ #if !defined INCLUDED_token_c_ #define INCLUDED_token_c_ #if defined HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include #include "token.h" /* for YWD_*WK_CNT */ #include "date-core.h" #if defined __INTEL_COMPILER /* we MUST return a char* */ # pragma warning (disable:2203) #elif defined __GNUC__ # pragma GCC diagnostic ignored "-Wcast-qual" #endif /* __INTEL_COMPILER */ struct dt_spec_s __tok_spec(const char *fp, const char **ep) { struct dt_spec_s res = spec_initialiser(); if (*fp != '%') { goto out; } next: switch (*++fp) { default: goto out; case 'F': res.spfl = DT_SPFL_N_DSTD; break; case 'T': res.spfl = DT_SPFL_N_TSTD; break; case 'Y': res.abbr = DT_SPMOD_LONG; case 'y': res.spfl = DT_SPFL_N_YEAR; break; case 'm': res.spfl = DT_SPFL_N_MON; break; case 'd': res.spfl = DT_SPFL_N_DCNT_MON; break; case 'u': res.wk_cnt = YWD_MONWK_CNT; case 'w': res.spfl = DT_SPFL_N_DCNT_WEEK; break; case 'D': case 'j': res.spfl = DT_SPFL_N_DCNT_YEAR; break; case 'c': res.spfl = DT_SPFL_N_WCNT_MON; break; case 'U': res.wk_cnt = YWD_SUNWK_CNT; res.spfl = DT_SPFL_N_WCNT_YEAR; break; case 'V': res.wk_cnt = YWD_ISOWK_CNT; res.spfl = DT_SPFL_N_WCNT_YEAR; break; case 'C': res.wk_cnt = YWD_ABSWK_CNT; res.spfl = DT_SPFL_N_WCNT_YEAR; break; case 'W': res.wk_cnt = YWD_MONWK_CNT; res.spfl = DT_SPFL_N_WCNT_YEAR; break; case 'A': res.abbr = DT_SPMOD_LONG; case 'a': res.spfl = DT_SPFL_S_WDAY; break; case 'B': res.abbr = DT_SPMOD_LONG; case 'b': case 'h': res.spfl = DT_SPFL_S_MON; break; /* time specs */ case 'I': res.sc12 = 1; case 'H': res.spfl = DT_SPFL_N_HOUR; break; case 'M': res.spfl = DT_SPFL_N_MIN; break; case 'S': res.spfl = DT_SPFL_N_SEC; break; case 'N': res.spfl = DT_SPFL_N_NANO; break; /* am/pm indicator */ case 'p': res.cap = 1; case 'P': res.spfl = DT_SPFL_S_AMPM; break; case 's': res.spfl = DT_SPFL_N_EPOCH; break; case 'Z': res.spfl = DT_SPFL_N_ZDIFF; break; case '_': /* abbrev modifier */ res.abbr = DT_SPMOD_ABBR; goto next; case '%': res.spfl = DT_SPFL_LIT_PERCENT; break; case 't': res.spfl = DT_SPFL_LIT_TAB; break; case 'n': res.spfl = DT_SPFL_LIT_NL; break; case 'Q': res.spfl = DT_SPFL_S_QTR; break; case 'q': res.spfl = DT_SPFL_N_QTR; break; case 'O': /* roman numerals modifier */ res.rom = 1; goto next; case '0': /* 0 padding modifier */ res.pad = DT_SPPAD_ZERO; goto next; case ' ': /* SPC padding modifier */ res.pad = DT_SPPAD_SPC; goto next; case '-': /* OMIT padding modifier */ res.pad = DT_SPPAD_OMIT; goto next; case 'r': /* real modifier */ res.tai = 1; goto next; case 'G': /* for compatibility with posix */ res.abbr = DT_SPMOD_LONG; case 'g': res.tai = 1U; res.spfl = DT_SPFL_N_YEAR; break; } /* check for ordinals */ if (res.spfl > DT_SPFL_UNK && res.spfl <= DT_SPFL_N_LAST && fp[1] == 't' && fp[2] == 'h' && !res.rom) { res.ord = 1; fp += 2; } /* check for bizda suffix */ if (res.spfl == DT_SPFL_N_DCNT_MON || res.spfl == DT_SPFL_N_DCNT_YEAR) { switch (*++fp) { case 'B': res.ab = BIZDA_BEFORE; case 'b': res.bizda = 1; break; default: fp--; break; } } out: if (ep != NULL) { *ep = (char*)(fp + 1); } return res; } #if defined __INTEL_COMPILER # pragma warning (default:2203) #elif defined __GNUC__ # pragma GCC diagnostic warning "-Wcast-qual" #endif /* __INTEL_COMPILER */ #endif /* INCLUDED_token_c_ */ dateutils-0.4.5/lib/token.h000066400000000000000000000111721335042257000155600ustar00rootroot00000000000000/*** token.h -- tokeniser specs and stuff * * Copyright (C) 2011-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of dateutils. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * **/ #if !defined INCLUDED_token_h_ #define INCLUDED_token_h_ /* spec tokeniser, spec flags plus modifiers and stuff */ typedef enum { DT_SPFL_UNK, /* generic dt standard */ DT_SPFL_N_STD, /* date specs */ /* %F, but generally stands for calendar's standard format */ DT_SPFL_N_DSTD, DT_SPFL_N_DFIRST = DT_SPFL_N_DSTD, /* year count, consecutive, %Y */ DT_SPFL_N_YEAR, /* month count within the year, recurring, %m */ DT_SPFL_N_MON, /* day count within the week, for 4-level calendars (%w) */ DT_SPFL_N_DCNT_WEEK, /* day count within the month, %d */ DT_SPFL_N_DCNT_MON, /* day count within the year, %D */ DT_SPFL_N_DCNT_YEAR, /* week count within the month, %c */ DT_SPFL_N_WCNT_MON, /* week count within the year, %C */ DT_SPFL_N_WCNT_YEAR, DT_SPFL_N_QTR, DT_SPFL_N_LAST = DT_SPFL_N_QTR, DT_SPFL_S_WDAY, DT_SPFL_S_DFIRST = DT_SPFL_S_WDAY, DT_SPFL_S_MON, DT_SPFL_S_QTR, DT_SPFL_S_DLAST = DT_SPFL_S_QTR, /* time specs */ DT_SPFL_N_SEC, DT_SPFL_N_TFIRST = DT_SPFL_N_SEC, DT_SPFL_N_MIN, DT_SPFL_N_HOUR, /* %T, but generally stands for calendar's standard format */ DT_SPFL_N_TSTD, /* %N nanoseconds, non-standard */ DT_SPFL_N_NANO, DT_SPFL_N_TLAST = DT_SPFL_N_NANO, /* date/time specs */ /* %s epoch spec, non-standard */ DT_SPFL_N_EPOCH, /* %Z zone difference */ DT_SPFL_N_ZDIFF, DT_SPFL_N_DTLAST = DT_SPFL_N_ZDIFF, DT_SPFL_S_AMPM, DT_SPFL_S_TFIRST = DT_SPFL_S_AMPM, DT_SPFL_S_TLAST = DT_SPFL_S_AMPM, DT_SPFL_LIT_PERCENT, DT_SPFL_LIT_TAB, DT_SPFL_LIT_NL, } dt_spfl_t; struct dt_spec_s { struct { /* ordinal flag, 01, 02, 03 -> 1st 2nd 3rd */ unsigned int ord:1U; /* roman numeral flag */ unsigned int rom:1U; /* want real seconds/minutes/etc. */ unsigned int tai:1U; /* for directions a(fter 0)/b(efore 1) */ unsigned int ab:1U; /* bizda */ unsigned int bizda:1U; /* pad to next octet */ unsigned int:3U; /* controls abbreviation */ enum { DT_SPMOD_NORM, DT_SPMOD_ABBR, DT_SPMOD_LONG, DT_SPMOD_ILL, } abbr:2U; /* control padding */ enum { DT_SPPAD_NONE, DT_SPPAD_ZERO, DT_SPPAD_SPC, DT_SPPAD_OMIT, } pad:2U; /** time specs */ /* long/short 24h v 12h scale */ unsigned int sc12:1U; /* capitalise am/pm indicator */ unsigned int cap:1U; /* week-count conventions */ unsigned int wk_cnt:2U; /* pad to the next word */ unsigned int:0U; }; dt_spfl_t spfl:8; }; #if !defined BIZDA_AFTER # define BIZDA_AFTER (0U)/*>*/ #endif /* !BIZDA_AFTER */ #if !defined BIZDA_BEFORE # define BIZDA_BEFORE (1U)/*<*/ #endif /* !BIZDA_BEFORE */ extern struct dt_spec_s __tok_spec(const char *fp, const char **ep); static inline __attribute__((pure, const)) struct dt_spec_s spec_initialiser(void) { #if defined HAVE_SLOPPY_STRUCTS_INIT static const struct dt_spec_s res = {}; #else static const struct dt_spec_s res; #endif /* HAVE_SLOPPY_STRUCTS_INIT */ return res; } static inline __attribute__((pure, const)) char padchar(struct dt_spec_s s) { return (char)(0x20U ^ ((s.pad < DT_SPPAD_SPC) << 4U)); } #endif /* INCLUDED_token_h_ */ dateutils-0.4.5/lib/tzmap.c000066400000000000000000000411031335042257000155630ustar00rootroot00000000000000/*** tzmap.c -- zonename maps * * Copyright (C) 2014-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of dateutils. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***/ #if defined HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ /* for fgetln() */ #define _NETBSD_SOURCE #define _DARWIN_SOURCE #define _ALL_SOURCE #include #include #include #include #include #if defined HAVE_SYS_STDINT_H # include #endif /* HAVE_SYS_STDINT_H */ #include #include #include #include #include #include #include #include "tzmap.h" #include "boops.h" #if !defined LIKELY # define LIKELY(_x) __builtin_expect((_x), 1) #endif /* !LIKELY */ #if !defined UNLIKELY # define UNLIKELY(_x) __builtin_expect((_x), 0) #endif /* UNLIKELY */ #if !defined UNUSED # define UNUSED(_x) _x __attribute__((unused)) #endif /* !UNUSED */ #if !defined countof # define countof(x) (sizeof(x) / sizeof(*x)) #endif /* !countof */ #define _paste(x, y) x ## y #define paste(x, y) _paste(x, y) #if !defined with # define with(args...) \ for (args, *paste(__ep, __LINE__) = (void*)1; \ paste(__ep, __LINE__); paste(__ep, __LINE__) = 0) #endif /* !with */ #if !defined HAVE_GETLINE && !defined HAVE_FGETLN /* as a service to people including this file in their project * but who might not necessarily run the corresponding AC_CHECK_FUNS * we assume that a getline() is available. */ # define HAVE_GETLINE 1 #endif /* !HAVE_GETLINE && !HAVE_FGETLN */ #if !defined DEFUN # define DEFUN #endif /* !DEFUN */ #if defined STANDALONE # if defined TZDIR static const char tzdir[] = TZDIR; # else /* !TZDIR */ static const char tzdir[] = "/usr/share/zoneinfo"; # endif /* TZDIR */ #endif /* STANDALONE */ #if defined STANDALONE static __attribute__((format(printf, 1, 2))) void error(const char *fmt, ...) { va_list vap; va_start(vap, fmt); vfprintf(stderr, fmt, vap); va_end(vap); fputc('\n', stderr); return; } static __attribute__((format(printf, 1, 2))) void serror(const char *fmt, ...) { va_list vap; va_start(vap, fmt); vfprintf(stderr, fmt, vap); va_end(vap); if (errno) { fputc(':', stderr); fputc(' ', stderr); fputs(strerror(errno), stderr); } fputc('\n', stderr); return; } static size_t xstrlncpy(char *restrict dst, size_t dsz, const char *src, size_t ssz) { if (ssz >= dsz) { ssz = dsz - 1U; } memcpy(dst, src, ssz); dst[ssz] = '\0'; return ssz; } #endif /* STANDALONE */ static void* deconst(const void *ptr) { return (char*)1 + ((const char*)ptr - (char*)1U); } static const void* align_to(size_t tz, const void *p) { uintptr_t x = (uintptr_t)p; if (x % tz) { x -= x % tz; } return (const void*)x; } #define ALIGN_TO(tz, p) align_to(sizeof(tz), p) /* public API */ static inline size_t tzm_file_size(tzmap_t m) { return m->flags[1U]; } static inline int tzm_fd(tzmap_t m) { return m->flags[0U]; } static inline const char* tzm_znames(tzmap_t m) { return m->data; } static inline size_t tzm_zname_size(tzmap_t m) { return m->off; } static inline const char* tzm_mnames(tzmap_t m) { return m->data + tzm_zname_size(m); } static inline size_t tzm_mname_size(tzmap_t m) { size_t fz = tzm_file_size(m); return fz - tzm_zname_size(m) - sizeof(*m); } DEFUN tzmap_t tzm_open(const char *fn) { #define FAIL (tzmap_t)MAP_FAILED #define TZMP (PROT_READ | PROT_WRITE) struct stat st[1U]; size_t fz; struct tzmap_s *m; int fd; if ((fd = open(fn, O_RDONLY)) < 0) { return NULL; } else if (fstat(fd, st) < 0) { goto clo; } else if ((fz = st->st_size) < sizeof(*m)) { goto clo; } else if ((m = mmap(0, fz, TZMP, MAP_PRIVATE, fd, 0)) == FAIL) { goto clo; } else if (memcmp(m->magic, TZM_MAGIC, sizeof(m->magic))) { goto mun; } /* turn offset into native endianness */ m->off = be32toh(m->off); /* also put fd and map size into m */ m->flags[0U] = (znoff_t)fd; m->flags[1U] = (znoff_t)st->st_size; /* and here we go */ return m; #undef FAIL #undef TZMP /* failure cases, clean up and return NULL */ mun: munmap(m, st->st_size); clo: close(fd); return NULL; } DEFUN void tzm_close(tzmap_t m) { size_t fz = tzm_file_size(m); int fd = tzm_fd(m); /* hopefully privately mapped */ munmap(deconst(m), fz); close(fd); return; } DEFUN const char* tzm_find(tzmap_t m, const char *mname) { /* lookup zname for MNAME */ const znoff_t *sp = (const void*)tzm_mnames(m); const znoff_t *ep = sp + tzm_mname_size(m) / sizeof(*sp) - 1U; const char *zns = tzm_znames(m); /* do a bisection now */ do { const char *mp = mname; const char *tp; const char *p; tp = (const char*)(sp + (ep - sp) / 2U); if (!*tp) { /* fast forward to the next entry */ tp += sizeof(*sp); } else { while (tp[-1] != '\0') { /* rewind to beginning */ tp--; } } /* store tp again */ p = tp; /* now unroll a strcmp */ for (; *mp && *mp == *tp; mp++, tp++); if (*mp - *tp < 0) { /* use lower half */ ep = (const znoff_t*)p - 1U; } else { /* forward to the next znoff_t alignment */ const znoff_t *op = (const znoff_t*)ALIGN_TO(znoff_t, tp - 1U) + 1U; if (*mp - *tp > 0) { /* use upper half */ sp = op + 1U; } else { /* found it */ return zns + (be32toh(*op) >> 8U); } } } while (sp < ep); return NULL; } #if defined STANDALONE /* array of all zone names */ static char *zns; static size_t znz; static ptrdiff_t zni; /* array for all mappee strings */ static znoff_t *mns; static size_t mnz; static ptrdiff_t mni; static void init_tzm(void) { zns = calloc(znz = 64U, sizeof(*zns)); mns = calloc(mnz = 64U, sizeof(*mns)); return; } static void free_tzm(void) { free(zns); free(mns); return; } static znoff_t tzm_find_zn(const char *zn, size_t zz) { char *restrict p = zns; const char *const ep = zns + znz; for (; p < ep && *p && strncmp(p, zn, zz); p += strlen(p), p++); if (*p) { /* found it, yay */ return p - zns; } /* otherwise append, first check if there's room */ if (p + zz + 4U >= ep) { /* compute new p */ ptrdiff_t d = p - zns; /* resize, double the size */ p = (zns = realloc(zns, znz *= 2U)) + d; memset(p, 0, (znz - (p - zns)) * sizeof(*zns)); } /* really append now */ memcpy(p, zn, zz); zni = (p - zns) + zz + 1U; return p - zns; } static void tzm_add_mn(const char *mn, size_t mz, znoff_t off) { znoff_t *restrict p = mns + mni; if (UNLIKELY(mz == 0U)) { /* useless */ return; } /* first check if there's room */ if (p + 1U + (mz + 4U/*alignment*/) / sizeof(off) >= mns + mnz) { /* resize, double the size */ p = (mns = realloc(mns, (mnz *= 2U) * sizeof(*mns))) + mni; memset((char*)p, 0, (mnz - (p - mns)) * sizeof(*mns)); } /* really append now */ memcpy(p, mn, mz); p += (mz - 1U) / sizeof(off) + 1U; *p++ = htobe32((off & 0xffffU)<< 8U); mni = p - mns; return; } static unsigned int exst_only_p; static const char *check_fn; static bool tzdir_zone_p(const char *zn, size_t zz) { struct stat st[1U]; char fullzn[256U] = {0}; if (*zn == '/') { /* absolute zonename? */ ; } else if (*zn) { /* relative zonename */ char *zp = fullzn; const char *const ep = fullzn + sizeof(fullzn); zp += xstrlncpy(zp, ep - zp, tzdir, sizeof(tzdir) - 1U); *zp++ = '/'; zp += xstrlncpy(zp, ep - zp, zn, zz); *zp = '\0'; } /* finally the actual check */ if (stat(fullzn, st) < 0) { return false; } return true; } static znoff_t parse_line(char *ln, size_t lz) { /* find the separator */ char *lp; znoff_t znp; if (UNLIKELY(ln == NULL || lz == 0U)) { /* finalise */ return NUL_ZNOFF; } if ((lp = memchr(ln, '\t', lz)) == NULL) { /* buggered line */ return NUL_ZNOFF; } else if (lp == ln) { return NUL_ZNOFF; } else if (*lp++ = '\0', *lp == '\0') { /* huh? no zone name, cunt off */ return NUL_ZNOFF; } else if (lp - ln > 256) { /* too long */ return NUL_ZNOFF; } else if (exst_only_p && !tzdir_zone_p(lp, ln + lz - lp)) { error("\ Warning: zone `%.*s' skipped: not present in global zone database", (int)(ln + lz - lp), lp); return NUL_ZNOFF; } else if ((znp = tzm_find_zn(lp, ln + lz - lp)) == -1U) { /* brilliant, can't add anything */ return NUL_ZNOFF; } tzm_add_mn(ln, lp - ln - 1U, znp); return znp; } static int check_line(char *ln, size_t lz) { static char last[256U]; static unsigned int lno; size_t cz; char *lp; int rc = 0; if (UNLIKELY(ln == NULL || lz == 0U)) { /* finalise */ lno = 0U; *last = '\0'; return 0; } /* advance line number */ lno++; #define CHECK_ERROR(fmt, args...) \ error("Error in %s:%u: " fmt, check_fn, lno, ## args) /* the actual checks here */ if ((lp = memchr(ln, '\t', lz)) == NULL) { /* buggered line */ CHECK_ERROR("no separator"); return -1; } else if (lp == ln) { CHECK_ERROR("no code"); return -1; } else if (*lp++ = '\0', *lp == '\0') { /* huh? no zone name, cunt off */ CHECK_ERROR("no zone name"); rc = -1; } if ((cz = lp - ln - 1U) >= sizeof(last)) { CHECK_ERROR("code too long (%zu chars, max is 255)", cz); rc = -1; } else if (strncmp(last, ln, cz) >= 0) { CHECK_ERROR("non-ascending order `%s' (after `%s')", ln, last); rc = -1; } /* make sure to memorise ln for the next run */ xstrlncpy(last, sizeof(last), ln, cz); /* it's none of our business really, but go through the zonenames * and check for their existence now */ if (!*lp) { /* already warned about this */ ; } else if (!tzdir_zone_p(lp, lz - (lp - ln))) { lp[lz - (lp - ln)] = '\0'; CHECK_ERROR("cannot find zone `%s' in TZDIR", lp); rc = -1; } #undef CHECK_ERROR return rc; } static int parse_file(const char *file) { char *line = NULL; size_t llen = 0U; FILE *fp; if (file == NULL) { fp = stdin; } else if ((fp = fopen(file, "r")) == NULL) { return -1; } #if defined HAVE_GETLINE for (ssize_t nrd; (nrd = getline(&line, &llen, fp)) > 0;) { parse_line(line, nrd - 1); } #elif defined HAVE_FGETLN while ((line = fgetln(fp, &llen)) != NULL && llen > 0U) { parse_line(line, llen - 1); } #else # error neither getline() nor fgetln() available, cannot read file line by line #endif /* GETLINE/FGETLN */ #if defined HAVE_GETLINE /* free line buffer resources */ free(line); #endif /* HAVE_GETLINE */ fclose(fp); return 0; } static bool tzmccp(FILE *fp) { static char buf[4U]; if (fread(buf, sizeof(*buf), countof(buf), fp) < sizeof(buf)) { /* definitely buggered */ ; } else if (!memcmp(buf, TZM_MAGIC, sizeof(buf))) { return true; } /* otherwise, good try, seek back to the beginning */ fseek(fp, 0, SEEK_SET); return false; } static int tzm_check(const char *fn) { tzmap_t m; int rc = 0; if ((m = tzm_open(fn)) == NULL) { serror("cannot open input file `%s'", fn); return -1; } { /* traverse them all */ const znoff_t *p = (const void*)tzm_mnames(m); const znoff_t *const ep = (const void*)((const char*)p + tzm_mname_size(m)); while (p < ep) { const char *mn = (const void*)p; size_t mz = strlen(mn); znoff_t off; const char *zn; size_t zz; p += (mz - 1U) / sizeof(*p) + 1U; off = be32toh(*p++) >> 8U; zn = m->data + off; zz = strlen(zn); if (!tzdir_zone_p(zn, zz)) { error("cannot find zone `%s' in TZDIR", zn); rc = -1; } } } tzm_close(m); return rc; } static int check_file(const char *file) { char *line = NULL; size_t llen = 0U; FILE *fp; int rc = 0; if (file == NULL) { fp = stdin; check_fn = "-"; } else if ((fp = fopen(check_fn = file, "r")) == NULL) { serror("Cannot open file `%s'", file); return -1; } else if (tzmccp(fp)) { /* oh yikes, can't use the line reader can we */ fclose(fp); return tzm_check(file); } #if defined HAVE_GETLINE for (ssize_t nrd; (nrd = getline(&line, &llen, fp)) > 0;) { rc |= check_line(line, nrd - 1); } #elif defined HAVE_FGETLN while ((line = fgetln(fp, &llen)) != NULL && llen > 0U) { rc |= check_line(line, llen - 1); } #else # error neither getline() nor fgetln() available, cannot read file line by line #endif /* GETLINE/FGETLN */ #if defined HAVE_GETLINE /* free line buffer resources */ free(line); #endif /* HAVE_GETLINE */ /* reset line checker */ check_line(NULL, 0U); /* and clear resources */ fclose(fp); return rc; } #endif /* STANDALONE */ #if defined STANDALONE #include "tzmap.yucc" static int cmd_cc(const struct yuck_cmd_cc_s argi[static 1U]) { const char *outf; int rc = 0; int ofd; /* reserve some space */ init_tzm(); /* establish environment */ exst_only_p = argi->existing_only_flag; if (parse_file(argi->args[0U]) < 0) { error("cannot read file `%s'", *argi->args ?: "stdin"); rc = 1; goto out; } else if ((outf = argi->output_arg ?: "tzcc.tzm", false)) { /* we used to make -o|--output mandatory */ ; } else if ((ofd = open(outf, O_RDWR | O_CREAT | O_TRUNC, 0666)) < 0) { serror("cannot open output file `%s'", outf); rc = 1; goto out; } /* generate a disk version now */ with (znoff_t off = zni) { static struct tzmap_s r = {TZM_MAGIC}; ssize_t sz; off = (off + sizeof(off) - 1U) / sizeof(off) * sizeof(off); r.off = htobe32(off); if (sz = sizeof(r), write(ofd, &r, sz) < sz) { goto trunc; } else if (sz = off, write(ofd, zns, sz) < sz) { goto trunc; } else if (sz = mni * sizeof(*mns), write(ofd, mns, sz) < sz) { goto trunc; } close(ofd); break; trunc: /* some write failed, leave a 0 byte file around */ close(ofd); unlink(outf); rc = 1; } out: free_tzm(); return rc; } static int cmd_show(const struct yuck_cmd_show_s argi[static 1U]) { const char *fn; tzmap_t m; int rc = 0; if ((fn = argi->tzmap_arg ?: "tzcc.tzm", false)) { /* we used to make -f|--tzmap mandatory */ ; } else if ((m = tzm_open(fn)) == NULL) { serror("cannot open input file `%s'", fn); return 1; } if (!argi->nargs) { /* dump mode */ const znoff_t *p = (const void*)tzm_mnames(m); const znoff_t *const ep = (const void*)((const char*)p + tzm_mname_size(m)); while (p < ep) { const char *mn = (const void*)p; size_t mz = strlen(mn); znoff_t off; p += (mz - 1U) / sizeof(*p) + 1U; off = be32toh(*p++) >> 8U; /* actually print the strings */ fputs(mn, stdout); fputc('\t', stdout); fputs(m->data + off, stdout); fputc('\n', stdout); } } /* otherwise */ for (size_t i = 0U; i < argi->nargs; i++) { const char *zn; if ((zn = tzm_find(m, argi->args[i])) != NULL) { puts(zn); } } /* and off we go */ tzm_close(m); return rc; } static int cmd_check(const struct yuck_cmd_check_s argi[static 1U]) { int rc = 0; for (size_t i = 0U; i < argi->nargs || i == 0U; i++) { rc |= check_file(argi->args[i]); } return -rc; } int main(int argc, char *argv[]) { yuck_t argi[1U]; int rc = 0; if (yuck_parse(argi, argc, argv) < 0) { rc = 1; goto out; } switch (argi->cmd) { case TZMAP_CMD_CC: rc = cmd_cc((void*)argi); break; case TZMAP_CMD_SHOW: rc = cmd_show((void*)argi); break; case TZMAP_CMD_CHECK: rc = cmd_check((void*)argi); break; default: rc = 1; break; } out: yuck_free(argi); return rc; } #endif /* STANDALONE */ /* tzmap.c ends here */ dateutils-0.4.5/lib/tzmap.h000066400000000000000000000045711335042257000156000ustar00rootroot00000000000000/*** tzmap.h -- zonename maps * * Copyright (C) 2014-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of uterus and dateutils. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***/ #if !defined INCLUDED_tzmap_h_ #define INCLUDED_tzmap_h_ #include /* ** Each file begins with. . . */ #define TZM_MAGIC "TZm1" typedef const struct tzmap_s *tzmap_t; typedef uint32_t znoff_t; #define NUL_ZNOFF ((uint32_t)-1) /** disk representation of tzm files */ struct tzmap_s { /* magic cookie, should be TZM_MAGIC */ const char magic[4U]; /* offset of mapped names, relative to data */ znoff_t off; /* just to round to 16 bytes boundary */ znoff_t flags[2U]; /* \nul term'd list of zonenames followed by mapped names */ const char data[]; }; /* public API */ extern tzmap_t tzm_open(const char *file); extern void tzm_close(tzmap_t); extern const char *tzm_find(tzmap_t m, const char *mname); #endif /* INCLUDED_tzmap_h_ */ dateutils-0.4.5/lib/tzmap.yuck000066400000000000000000000007661335042257000163260ustar00rootroot00000000000000Usage: tzmap COMMAND [ARG]... Generate or inspect zoneinfo name map files. Usage: tzmap cc [FILE]... Generate a map to zoneinfo names suitable for dateutils. -o, --output=FILE Output compiled map into FILE. -e, --existing-only Only map currently existing zones. Usage: tzmap show [MNAME]... Show mapped zonename for MNAMEs, if omitted show all entries from the specified tzmap file. -f, --tzmap=FILE Use FILE. Usage: tzmap check [FILE]... Check IANA zonenames in FILEs. dateutils-0.4.5/lib/tzraw.c000066400000000000000000000417771335042257000156200ustar00rootroot00000000000000/*** tzraw.c -- reader for olson database zoneinfo files * * Copyright (C) 2009-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of uterus and dateutils. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***/ /* implementation part of tzraw.h */ #if !defined INCLUDED_tzraw_c_ #define INCLUDED_tzraw_c_ #if defined HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #if defined MAP_ANON_NEEDS_DARWIN_SOURCE # define _DARWIN_C_SOURCE #endif /* MAP_ANON_NEEDS_DARWIN_SOURCE */ #if defined MAP_ANON_NEEDS_ALL_SOURCE # define _ALL_SOURCE #endif /* MAP_ANON_NEEDS_ALL_SOURCE */ #include #include #include #include #include #include #include #include #include #include #include #if defined HAVE_TZFILE_H # include #endif /* HAVE_TZFILE_H */ /* for be/le conversions */ #include "boops.h" /* for LIKELY/UNLIKELY/etc. */ #include "nifty.h" /* me own header, innit */ #include "tzraw.h" /* for leap corrections */ #include "leap-seconds.h" #if !defined DEFUN # define DEFUN #endif /* !DEFUN */ #if !defined MAP_ANONYMOUS && defined MAP_ANON # define MAP_ANONYMOUS (MAP_ANON) #elif !defined MAP_ANON # define MAP_ANON (0x1000U) #endif /* MAP_ANON->MAP_ANONYMOUS */ typedef struct zih_s *zih_t; typedef int32_t *ztr_t; typedef uint8_t *zty_t; typedef struct ztrdtl_s *ztrdtl_t; typedef char *znam_t; /* this is tzhead but better */ struct zih_s { /* magic */ char tzh_magic[4]; /* must be '2' now, as of 2005 */ char tzh_version[1]; /* reserved--must be zero */ char tzh_reserved[15]; /* number of transition time flags in gmt */ uint32_t tzh_ttisgmtcnt; /* number of transition time flags in local time */ uint32_t tzh_ttisstdcnt; /* number of recorded leap seconds */ uint32_t tzh_leapcnt; /* number of recorded transition times */ uint32_t tzh_timecnt; /* number of local time type */ uint32_t tzh_typecnt; /* number of abbreviation chars */ uint32_t tzh_charcnt; }; /* this one must be packed to account for the packed file layout */ struct ztrdtl_s { int32_t offs; uint8_t dstp; uint8_t abbr; } __attribute__((packed)); /* convenience struct where we copy all the good things into one */ struct zspec_s { int32_t since; unsigned int offs:31; unsigned int dstp:1; znam_t name; } __attribute__((packed, aligned(16))); /* for leap second transitions */ struct zleap_tr_s { /* cut-off stamp */ int32_t t; /* cumulative correction since T */ int32_t corr; }; /* leap second support missing */ struct zif_s { size_t mpsz; zih_t hdr; /* transitions */ ztr_t trs; /* types */ zty_t tys; /* type array, deser'd, transition details array */ ztrdtl_t tda; /* zonename array */ znam_t zn; /* file descriptor, if >0 this also means all data is in BE */ int fd; /* for special zones */ coord_zone_t cz; /* zone caching, between PREV and NEXT the offset is OFFS */ struct zrng_s cache; }; #if defined TZDIR static const char tzdir[] = TZDIR; #else /* !TZDIR */ static const char tzdir[] = "/usr/share/zoneinfo"; #endif #if defined ZONEINFO_UTC_RIGHT /* where can we deduce some info for our coordinated zones */ static const char coord_fn[] = ZONEINFO_UTC_RIGHT; #elif defined ZONEINFO_UTC static const char coord_fn[] = ZONEINFO_UTC; #else /* !ZONEINFO_UTC_RIGHT && !ZONEINFO_UTC */ static const char coord_fn[] = "/usr/share/zoneinfo/UTC"; #endif /* ZONEINFO_UTC_RIGHT || ZONEINFO_UTC */ #define PROT_MEMMAP PROT_READ | PROT_WRITE #define MAP_MEMMAP MAP_PRIVATE | MAP_ANON #define AS_MUT_ZIF(x) ((struct zif_s*)deconst(x)) /* special zone names */ static const char coord_zones[][4] = { "", "UTC", "TAI", "GPS", }; static void* deconst(const void *ptr) { return (char*)1 + ((const char*)ptr - (char*)1U); } /** * Return the total number of transitions in zoneinfo file Z. */ DEFUN inline size_t zif_ntrans(const struct zif_s z[static 1U]) { return z->hdr->tzh_timecnt; } /** * Return the total number of transition types in zoneinfo file Z. */ static inline size_t zif_ntypes(const struct zif_s z[static 1U]) { return z->hdr->tzh_typecnt; } /** * Return the total number of transitions in zoneinfo file Z. */ static inline size_t zif_nchars(const struct zif_s z[static 1U]) { return z->hdr->tzh_charcnt; } /** * Return the total number of leap second transitions. */ static __attribute__((unused)) inline size_t zif_nleaps(const struct zif_s z[static 1U]) { return z->hdr->tzh_leapcnt; } /** * Return the transition time stamp of the N-th transition in Z. */ static inline int32_t zif_trans(const struct zif_s z[static 1U], int n) { size_t ntr = zif_ntrans(z); if (UNLIKELY(!ntr || n < 0)) { /* return earliest possible stamp */ return INT_MIN; } else if (UNLIKELY(n >= (ssize_t)ntr)) { /* return last known stamp */ return z->trs[ntr - 1U]; } /* otherwise return n-th stamp */ return z->trs[n]; } /** * Return the transition type index of the N-th transition in Z. */ static inline uint8_t zif_type(const struct zif_s z[static 1U], int n) { size_t ntr = zif_ntrans(z); if (UNLIKELY(!ntr || n < 0)) { /* return unknown type */ return 0; } else if (UNLIKELY(n >= (ssize_t)ntr)) { /* return last known type */ return z->tys[ntr - 1U]; } /* otherwise return n-th type */ return z->tys[n]; } /** * Return the transition details after the N-th transition in Z. */ inline struct ztrdtl_s zif_trdtl(const struct zif_s z[static 1U], int n) { /* no bound check! */ struct ztrdtl_s res; uint8_t idx = zif_type(z, n); res = z->tda[idx]; return res; } /** * Return the gmt offset the N-th transition in Z. */ static inline int32_t zif_troffs(const struct zif_s z[static 1U], int n) { /* no bound check! */ uint8_t idx = zif_type(z, n); return z->tda[idx].offs; } /** * Return the zonename after the N-th transition in Z. */ static __attribute__((unused)) inline znam_t zif_trname(const struct zif_s z[static 1U], int n) { /* no bound check! */ uint8_t idx = zif_type(z, n); uint8_t jdx = z->tda[idx].abbr; return z->zn + jdx; } /** * Return a succinct summary of the situation after transition N in Z. */ static __attribute__((unused)) inline struct zspec_s zif_spec(const struct zif_s z[static 1U], int n) { struct zspec_s res; uint8_t idx = zif_type(z, n); uint8_t jdx = z->tda[idx].abbr; res.since = zif_trans(z, n); res.offs = z->tda[idx].offs; res.dstp = z->tda[idx].dstp; res.name = z->zn + jdx; return res; } static coord_zone_t coord_zone(const char *zone) { for (coord_zone_t i = TZCZ_UTC; i < TZCZ_NZONE; i++) { if (strcmp(zone, coord_zones[i]) == 0) { return i; } } return TZCZ_UNK; } static int __open_zif(const char *file) { if (file == NULL || file[0] == '\0') { return -1; } else if (file[0] != '/') { /* not an absolute file name */ size_t len = strlen(file); size_t tzd_len = sizeof(tzdir) - 1; char new[tzd_len + 1U + len + 1U]; char *tmp = new + tzd_len; memcpy(new, tzdir, tzd_len); *tmp++ = '/'; memcpy(tmp, file, len + 1U); return open(new, O_RDONLY, 0644); } /* absolute file name, just try with that one then */ return open(file, O_RDONLY, 0644); } static void __init_zif(struct zif_s z[static 1U]) { size_t ntr; size_t nty; if (z->fd > STDIN_FILENO) { /* probably in BE then, eh? */ ntr = be32toh(zif_ntrans(z)); nty = be32toh(zif_ntypes(z)); } else { ntr = zif_ntrans(z); nty = zif_ntypes(z); } z->trs = (ztr_t)(z->hdr + 1); z->tys = (zty_t)(z->trs + ntr); z->tda = (ztrdtl_t)(z->tys + ntr); z->zn = (char*)(z->tda + nty); return; } static int __read_zif(struct zif_s tgt[static 1U], int fd) { struct stat st; if (fstat(fd, &st) < 0) { return -1; } else if (st.st_size <= 4) { return -1; } tgt->mpsz = st.st_size; tgt->fd = fd; tgt->hdr = mmap(NULL, tgt->mpsz, PROT_READ, MAP_SHARED, fd, 0); if (tgt->hdr == MAP_FAILED) { return -1; } /* all clear so far, populate */ __init_zif(tgt); return 0; } static void __conv_hdr(struct zih_s tgt[static 1U], const struct zih_s src[static 1U]) { /* copy SRC to TGT doing byte-order conversions on the way */ memcpy(tgt, src, offsetof(struct zih_s, tzh_ttisgmtcnt)); tgt->tzh_ttisgmtcnt = be32toh(src->tzh_ttisgmtcnt); tgt->tzh_ttisstdcnt = be32toh(src->tzh_ttisstdcnt); tgt->tzh_leapcnt = be32toh(src->tzh_leapcnt); tgt->tzh_timecnt = be32toh(src->tzh_timecnt); tgt->tzh_typecnt = be32toh(src->tzh_typecnt); tgt->tzh_charcnt = be32toh(src->tzh_charcnt); return; } static void __conv_zif(struct zif_s tgt[static 1U], const struct zif_s src[static 1U]) { size_t ntr; size_t nty; size_t nch; /* convert header to hbo */ __conv_hdr(tgt->hdr, src->hdr); /* everything in host byte-order already */ ntr = zif_ntrans(tgt); nty = zif_ntypes(tgt); nch = zif_nchars(tgt); __init_zif(tgt); /* transition vector */ for (size_t i = 0; i < ntr; i++) { tgt->trs[i] = be32toh(src->trs[i]); } /* type vector, nothing to byte-swap here */ memcpy(tgt->tys, src->tys, ntr * sizeof(*tgt->tys)); /* transition details vector */ for (size_t i = 0; i < nty; i++) { tgt->tda[i].offs = be32toh(src->tda[i].offs); tgt->tda[i].dstp = src->tda[i].dstp; tgt->tda[i].abbr = src->tda[i].abbr; } /* zone name array */ memcpy(tgt->zn, src->zn, nch * sizeof(*tgt->zn)); return; } static struct zif_s* __copy_conv(const struct zif_s z[static 1U]) { /* copy Z and do byte-order conversions */ size_t mpsz; struct zif_s *res = NULL; /* compute a size */ mpsz = z->mpsz + sizeof(*z); /* we'll mmap ourselves a slightly larger struct so * res + 1 points to the header, while res + 0 is the zif_t */ res = mmap(NULL, mpsz, PROT_MEMMAP, MAP_MEMMAP, -1, 0); if (UNLIKELY(res == MAP_FAILED)) { return NULL; } /* great, now to some initial assignments */ res->mpsz = mpsz; res->hdr = (void*)(res + 1); /* make sure we denote that this isnt connected to a file */ res->fd = -1; /* copy the flags though */ res->cz = z->cz; /* convert the header and payload now */ __conv_zif(res, z); /* that's all :) */ return res; } static struct zif_s* __copy(const struct zif_s z[static 1U]) { /* copy Z into a newly allocated zif_t object * if applicable also perform byte-order conversions */ struct zif_s *res; if (z->fd > STDIN_FILENO) { return __copy_conv(z); } /* otherwise it's a plain copy */ res = mmap(NULL, z->mpsz, PROT_MEMMAP, MAP_MEMMAP, -1, 0); if (UNLIKELY(res == MAP_FAILED)) { return NULL; } memcpy(res, z, z->mpsz); __init_zif(res); return res; } DEFUN zif_t zif_copy(zif_t z) { /* copy Z into a newly allocated zif_t object * if applicable also perform byte-order conversions */ if (UNLIKELY(z == NULL)) { /* no need to bother */ return NULL; } return __copy(z); } static void __close(const struct zif_s z[static 1U]) { if (z->fd > STDIN_FILENO) { close(z->fd); } /* check if z is in mmap()'d space */ if (z->hdr == MAP_FAILED) { /* not sure what to do */ ; } else if ((z + 1) != (void*)z->hdr) { /* z->hdr is mmapped, z is not */ munmap((void*)z->hdr, z->mpsz); } else { munmap(deconst(z), z->mpsz); } return; } DEFUN void zif_close(zif_t z) { if (UNLIKELY(z == NULL)) { /* nothing to do */ return; } __close((const void*)z); return; } DEFUN zif_t zif_open(const char *file) { coord_zone_t cz; int fd; struct zif_s tmp[1]; struct zif_s *res; /* check for special time zones */ if ((cz = coord_zone(file)) > TZCZ_UNK) { /* use UTC file */ file = coord_fn; } if (UNLIKELY((fd = __open_zif(file)) < STDIN_FILENO)) { return NULL; } else if (UNLIKELY(__read_zif(tmp, fd) < 0)) { return NULL; } /* otherwise all's fine, it's still BE * assign the coord zone type if any and convert to host byte-order */ tmp->cz = cz; res = __copy(tmp); __close(tmp); return res; } /* for leap corrections */ #include "leap-seconds.def" static inline int __find_trno(const struct zif_s z[static 1U], int32_t t, int min, int max) { /* find the last transition before T, T is expected to be UTC * if T is before any known transition return -1 */ if (UNLIKELY(max == 0)) { /* special case */ return -1; } else if (UNLIKELY(t < zif_trans(z, min))) { return -1; } else if (UNLIKELY(t > zif_trans(z, max))) { return max - 1; } do { int32_t tl, tu; int this = (min + max) / 2; tl = zif_trans(z, this); tu = zif_trans(z, this + 1); if (t >= tl && t < tu) { /* found him */ return this; } else if (t >= tu) { min = this; } else if (t < tl) { max = this; } } while (true); /* not reached */ } DEFUN inline int zif_find_trans(zif_t z, int32_t t) { /* find the last transition before T, T is expected to be UTC * if T is before any known transition return -1 */ int max = zif_ntrans(z); int min = 0; return __find_trno(z, t, min, max); } static struct zrng_s __find_zrng(const struct zif_s z[static 1U], int32_t t, int min, int max) { struct zrng_s res; int trno; trno = __find_trno(z, t, min, max); res.prev = zif_trans(z, trno); if (UNLIKELY(trno <= 0 && t < res.prev)) { res.trno = 0U; res.prev = INT_MIN; /* assume the first offset has always been there */ res.next = res.prev; } else if (UNLIKELY(trno < 0)) { /* special case where no transitions are recorded */ res.trno = 0U; res.prev = INT_MIN; res.next = INT_MAX; } else { res.trno = (uint8_t)trno; if (LIKELY(trno + 1U < zif_ntrans(z))) { res.next = zif_trans(z, trno + 1U); } else { res.next = INT_MAX; } } res.offs = zif_troffs(z, res.trno); return res; } DEFUN inline struct zrng_s zif_find_zrng(zif_t z, int32_t t) { /* find the last transition before time, time is expected to be UTC */ int max = zif_ntrans(z); int min = 0; return __find_zrng(z, t, min, max); } static int32_t __tai_offs(int32_t t) { /* difference of TAI and UTC at epoch instant */ zidx_t zi = leaps_before_si32(leaps_s, nleaps_corr, t); return leaps_corr[zi]; } static int32_t __gps_offs(int32_t t) { /* TAI - GPS = 19 on 1980-01-06, so use that identity here */ const int32_t gps_offs_epoch = 19; if (UNLIKELY(t < 315964800)) { return 0; } return __tai_offs(t) - gps_offs_epoch; } static int32_t __offs(struct zif_s z[static 1U], int32_t t) { /* return the offset of T in Z and cache the result. */ int min; size_t max; switch (z->cz) { default: case TZCZ_UNK: break; case TZCZ_UTC: return 0; case TZCZ_TAI: return __tai_offs(t); case TZCZ_GPS: return __gps_offs(t); } /* use the classic code */ if (LIKELY(t >= z->cache.prev && t < z->cache.next)) { /* use the cached offset */ return z->cache.offs; } else if (t >= z->cache.next) { min = z->cache.trno + 1; max = zif_ntrans(z); } else if (t < z->cache.prev) { max = z->cache.trno; min = 0; } else { /* we shouldn't end up here at all */ min = 0; max = 0; } return (z->cache = __find_zrng(z, t, min, max)).offs; } DEFUN int32_t zif_utc_time(zif_t z, int32_t t) { /* here's the setup, given t in local time, we denote the corresponding * UTC time by t' = t - x' where x' is the true offset * however, since we do not know the offset in advance, we have to solve * for an estimate of the offset x: * t - x + x' = t, or equivalently t - x = t' or as a root finding problem * x' - x = 0. * To make this iterative we just solve: * x_{i+1} - x_i = 0, where x_{i+1} = o(t - x_i) and o maps a given * time stamp to an offset. */ /* make me use the cache please! */ /* let's go */ int32_t xi = 0; int32_t xj; int32_t old = -1; /* jump off the cliff if Z is nought */ if (UNLIKELY(z == NULL)) { return t; } while ((xj = __offs(AS_MUT_ZIF(z), t - xi)) != xi && xi != old) { old = xi = xj; } return t - xj; } /* convert utc to local */ DEFUN int32_t zif_local_time(zif_t z, int32_t t) { /* jump off the cliff if Z is nought */ if (UNLIKELY(z == NULL)) { return t; } return t + __offs(AS_MUT_ZIF(z), t); } #endif /* INCLUDED_tzraw_c_ */ /* tzraw.c ends here */ dateutils-0.4.5/lib/tzraw.h000066400000000000000000000122361335042257000156110ustar00rootroot00000000000000/*** tzraw.h -- reader for olson database zoneinfo files * * Copyright (C) 2009-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of uterus and dateutils. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***/ #if !defined INCLUDED_tzraw_h_ #define INCLUDED_tzraw_h_ #include #include #include "leaps.h" #if defined __cplusplus extern "C" { #endif /* __cplusplus */ /* ** Each file begins with. . . */ #define TZ_MAGIC "TZif" #if 0 struct tzhead { char tzh_magic[4]; /* TZ_MAGIC */ char tzh_version[1]; /* '\0' or '2' as of 2005 */ char tzh_reserved[15]; /* reserved--must be zero */ char tzh_ttisgmtcnt[4]; /* coded number of trans. time flags */ char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */ char tzh_leapcnt[4]; /* coded number of leap seconds */ char tzh_timecnt[4]; /* coded number of transition times */ char tzh_typecnt[4]; /* coded number of local time types */ char tzh_charcnt[4]; /* coded number of abbr. chars */ }; /* ** . . .followed by. . . ** ** tzh_timecnt (char [4])s coded transition times a la time(2) ** tzh_timecnt (unsigned char)s types of local time starting at above ** tzh_typecnt repetitions of ** one (char [4]) coded UTC offset in seconds ** one (unsigned char) used to set tm_isdst ** one (unsigned char) that's an abbreviation list index ** tzh_charcnt (char)s '\0'-terminated zone abbreviations ** tzh_leapcnt repetitions of ** one (char [4]) coded leap second transition times ** one (char [4]) total correction after above ** tzh_ttisstdcnt (char)s indexed by type; if TRUE, transition ** time is standard time, if FALSE, ** transition time is wall clock time ** if absent, transition times are ** assumed to be wall clock time ** tzh_ttisgmtcnt (char)s indexed by type; if TRUE, transition ** time is UTC, if FALSE, ** transition time is local time ** if absent, transition times are ** assumed to be local time */ /* ** If tzh_version is '2' or greater, the above is followed by a second instance ** of tzhead and a second instance of the data in which each coded transition ** time uses 8 rather than 4 chars, ** then a POSIX-TZ-environment-variable-style string for use in handling ** instants after the last transition time stored in the file ** (with nothing between the newlines if there is no POSIX representation for ** such instants). */ #endif /* 0 */ /* now our view on things */ typedef const struct zif_s *zif_t; typedef enum { TZCZ_UNK, TZCZ_UTC, TZCZ_TAI, TZCZ_GPS, TZCZ_NZONE, } coord_zone_t; /* for the one tool that needs raw transitions */ struct zrng_s { int32_t prev, next; signed int offs:24; unsigned int trno:8; } __attribute__((packed)); /** * Open the zoneinfo file FILE. * FILE can be absolute or relative to the configured TZDIR path. * FILE can also name virtual zones such as GPS or TAI. */ extern zif_t zif_open(const char *file); /** * Close the zoneinfo file reader and free associated resources. */ extern void zif_close(zif_t); /** * Copy the zoneinfo structure. */ extern zif_t zif_copy(zif_t); /** * Find the most recent transition in Z before T. */ extern int zif_find_trans(zif_t z, int32_t t); /** * Find a range of transitions in Z that T belongs to. */ extern struct zrng_s zif_find_zrng(zif_t z, int32_t t); /** * Given T in local time specified by Z, return a T in UTC. */ extern int32_t zif_utc_time(zif_t z, int32_t t); /** * Given T in UTC, return a T in local time specified by Z. */ extern int32_t zif_local_time(zif_t z, int32_t t); /* exposure for specific zif-inspecting tools (dzone(1) for one) */ extern size_t zif_ntrans(zif_t z); extern struct ztrdtl_s zif_trdtl(zif_t z, int n); #if defined __cplusplus } #endif /* __cplusplus */ #endif /* INCLUDED_tzraw_h_ */ dateutils-0.4.5/lib/version.c.in000066400000000000000000000001451335042257000165230ustar00rootroot00000000000000/* -*- c -*- */ #include "version.h" const char dateutils_version_string[] = "YUCK_SCMVER_VERSION"; dateutils-0.4.5/lib/version.h000066400000000000000000000002721335042257000161240ustar00rootroot00000000000000#ifndef INCLUDED_version_h_ #define INCLUDED_version_h_ extern const char dateutils_version_string[]; #define package_version dateutils_version_string #endif /* INCLUDED_version_h_ */ dateutils-0.4.5/lib/yd.c000066400000000000000000000446231335042257000150560ustar00rootroot00000000000000/*** yd.c -- guts for yd dates that consist of a year and a year-day * * Copyright (C) 2010-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of dateutils. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * **/ /* for convenience year related stuff will be collected in here as well */ /* set aspect temporarily */ #define ASPECT_YD /* permanent aspect, to be read as have we ever seen aspect_yd */ #if !defined ASPECT_YD_ #define ASPECT_YD_ #endif /* !ASPECT_YD_ */ #include "nifty.h" #if !defined DEFUN # define DEFUN #endif /* !DEFUN */ /* algo choices for jan01 wd determination */ #if defined GET_JAN01_WDAY_FULL_LOOKUP #elif defined GET_JAN01_WDAY_28Y_LOOKUP #elif defined GET_JAN01_WDAY_28Y_SWITCH #elif defined GET_JAN01_WDAY_SAKAMOTO #else # define GET_JAN01_WDAY_28Y_LOOKUP #endif /* year + mon-dom -> yd algos */ #if defined YMD_GET_YD_LOOKUP #elif defined YMD_GET_YD_DIVREM #else # define YMD_GET_YD_LOOKUP #endif /* yd -> mon-dom algos */ #if defined GET_MD_FREUNDT #elif defined GET_MD_TRIMESTER #else # define GET_MD_FREUNDT #endif #if !defined YD_ASPECT_HELPERS_ #define YD_ASPECT_HELPERS_ #if defined GET_JAN01_WDAY_FULL_LOOKUP # define M (unsigned int)(DT_MONDAY) # define T (unsigned int)(DT_TUESDAY) # define W (unsigned int)(DT_WEDNESDAY) # define R (unsigned int)(DT_THURSDAY) # define F (unsigned int)(DT_FRIDAY) # define A (unsigned int)(DT_SATURDAY) # define S (unsigned int)(DT_SUNDAY) static const __jan01_wday_block_t __jan01_wday[] = { #define __JAN01_WDAY_BEG (1920) { /* 1920 - 1929 */ R, A, S, M, T, R, F, A, S, T, 0, }, { /* 1930 - 1939 */ W, R, F, S, M, T, W, F, A, S, 0, }, { /* 1940 - 1949 */ M, W, R, F, A, M, T, W, R, A, 0, }, { /* 1950 - 1959 */ S, M, T, R, F, A, S, T, W, R, 0, }, { /* 1960 - 1969 */ F, S, M, T, W, F, A, S, M, W, 0, }, { /* 1970 - 1979 */ R, F, A, M, T, W, R, A, S, M, 0, }, { /* 1980 - 1989 */ T, R, F, A, S, T, W, R, F, S, 0, }, { /* 1990 - 1999 */ M, T, W, F, A, S, M, W, R, F, 0, }, { /* 2000 - 2009 */ A, M, T, W, R, A, S, M, T, R, 0, }, { /* 2010 - 2019 */ F, A, S, T, W, R, F, S, M, T, 0, }, { /* 2020 - 2029 */ W, F, A, S, M, W, R, F, A, M, 0, }, { /* 2030 - 2039 */ T, W, R, A, S, M, T, R, F, A, 0, }, { /* 2040 - 2049 */ S, T, W, R, F, S, M, T, W, F, 0, }, { /* 2050 - 2059 */ A, S, M, W, R, F, A, M, T, W, 0, } /* 2060 - 2069 is 1920 - 1929 */ #define __JAN01_WDAY_END (2059) }; # undef M # undef T # undef W # undef R # undef F # undef A # undef S static inline __attribute__((const, pure)) __jan01_wday_block_t __get_jan01_block(unsigned int year) { return __jan01_wday[(year - __JAN01_WDAY_BEG) / __JAN01_Y_PER_B]; } static inline __attribute__((const, pure)) dt_dow_t __get_jan01_wday(unsigned int year) { /* get the weekday of jan01 in YEAR */ unsigned int res; __jan01_wday_block_t j01b; if (UNLIKELY(year < __JAN01_WDAY_BEG)) { /* use the 140y period property */ while ((year += 140) < __JAN01_WDAY_BEG); } else if (year > __JAN01_WDAY_END) { /* use the 140y period property */ while ((year -= 140) > __JAN01_WDAY_END); } j01b = __get_jan01_block(year); switch (year % 10) { default: res = DT_MIRACLEDAY; break; case 0: res = j01b.y0; break; case 1: res = j01b.y1; break; case 2: res = j01b.y2; break; case 3: res = j01b.y3; break; case 4: res = j01b.y4; break; case 5: res = j01b.y5; break; case 6: res = j01b.y6; break; case 7: res = j01b.y7; break; case 8: res = j01b.y8; break; case 9: res = j01b.y9; break; } return (dt_dow_t)res; } #elif defined GET_JAN01_WDAY_28Y_LOOKUP # define M (DT_MONDAY) # define T (DT_TUESDAY) # define W (DT_WEDNESDAY) # define R (DT_THURSDAY) # define F (DT_FRIDAY) # define A (DT_SATURDAY) # define S (DT_SUNDAY) static const dt_dow_t __jan01_28y_wday[] = { /* 1904 - 1910 */ F, S, M, T, W, F, A, /* 1911 - 1917 */ S, M, W, R, F, A, M, /* 1918 - 1924 */ T, W, R, A, S, M, T, /* 1925 - 1931 */ R, F, A, S, T, W, R, }; # undef M # undef T # undef W # undef R # undef F # undef A # undef S static __attribute__((const, pure)) unsigned int __get_28y_year_equiv(unsigned year) { /* the 28y cycle works for 1901 to 2100, for other years find an equivalent */ year = year % 400U; if (year > 300U) { return year + 1600U; } else if (year > 200U) { return year + 1724U; } else if (year > 100U) { return year + 1820U; } return year + 2000; } static inline __attribute__((const, pure)) dt_dow_t __get_jan01_wday(unsigned int year) { /* get the weekday of jan01 in YEAR * using the 28y cycle thats valid till the year 2399 * 1920 = 16 mod 28 */ #if !defined WITH_FAST_ARITH if (UNLIKELY(year > 2100U || #if DT_MIN_YEAR == 1917 0 #elif DT_MIN_YEAR == 1753 year < 1901U #elif DT_MIN_YEAR == 1601 year < 1901U #endif )) { year = __get_28y_year_equiv(year); } #endif /* !WITH_FAST_ARITH */ return __jan01_28y_wday[year % 28U]; } #elif defined GET_JAN01_WDAY_28Y_SWITCH static inline __attribute__((const, pure)) dt_dow_t __get_jan01_wday(unsigned int year) { /* get the weekday of jan01 in YEAR * using the 28y cycle thats valid till the year 2399 * 1920 = 16 mod 28 * switch variant */ # define M (DT_MONDAY) # define T (DT_TUESDAY) # define W (DT_WEDNESDAY) # define R (DT_THURSDAY) # define F (DT_FRIDAY) # define A (DT_SATURDAY) # define S (DT_SUNDAY) switch (year % 28) { case 0: return F; case 1: return S; case 2: return M; case 3: return T; case 4: return W; case 5: return F; case 6: return A; case 7: return S; case 8: return M; case 9: return W; case 10: return R; case 11: return F; case 12: return A; case 13: return M; case 14: return T; case 15: return W; case 16: return R; case 17: return A; case 18: return S; case 19: return M; case 20: return T; case 21: return R; case 22: return F; case 23: return A; case 24: return S; case 25: return T; case 26: return W; case 27: return R; default: return DT_MIRACLEDAY; } # undef M # undef T # undef W # undef R # undef F # undef A # undef S } #elif defined GET_JAN01_WDAY_SAKAMOTO static inline __attribute__((const, pure)) dt_dow_t __get_jan01_wday(unsigned int year) { unsigned int res; year--, res = year + year / 4 - year / 100 + year / 400 + 1; res %= GREG_DAYS_P_WEEK; return (dt_dow_t)(res ?: DT_SUNDAY); } #endif /* GET_JAN01_WDAY_* */ #if defined YMD_GET_YD_LOOKUP static inline __attribute__((const, pure)) unsigned int __md_get_yday(unsigned int year, unsigned int mon, unsigned int dom) { static uint16_t __mon_yday[] = { /* this is \sum ml, * first element is a bit set of leap days to add */ 0xfff8, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; return __mon_yday[mon] + dom + UNLIKELY(__leapp(year) && mon >= 3); } #elif defined YMD_GET_YD_DIVREM static inline __attribute__((const, pure)) unsigned int __md_get_yday(unsigned int year, unsigned int mon, unsigned int dom) { #define SL(x) ((x) * 5) #define GET_REM(x) ((rem >> SL(x)) & 0x1f) static const uint64_t rem = (19ULL << SL(0)) | (18ULL << SL(1)) | (14ULL << SL(2)) | (13ULL << SL(3)) | (11ULL << SL(4)) | (10ULL << SL(5)) | (8ULL << SL(6)) | (7ULL << SL(7)) | (6ULL << SL(8)) | (4ULL << SL(9)) | (3ULL << SL(10)) | (1ULL << SL(11)) | (0ULL << SL(12)); return (mon - 1) * 32 + GET_REM(mon - 1) - 19 + dom + UNLIKELY(__leapp(year) && mon >= 3); #undef GET_REM #undef SL } #endif /* YMD_GET_YD_* */ #if defined GET_MD_FREUNDT /* Freundt's 32-adic algo */ static __attribute__((const, pure)) struct __md_s __yday_get_md(unsigned int year, unsigned int doy) { /* Given a year and the day of the year, return gregorian month + dom * we use some clever maths to invert __mon_yday[] above * you see __mon_yday[] + 19 divrem 32 is * F 0 0 19 * G 31 1 18 * H 59 2 14 * J 90 3 13 * K 120 4 11 * M 151 5 10 * N 181 6 8 * Q 212 7 7 * U 243 8 6 * V 273 9 4 * X 304 10 3 * Z 334 11 1 * 365 12 0 * * Now the key is to store only the remainders in a clever way. * * So in total the table we store is 5bit remainders of * __mon_yday[] + 19 % 32 */ #define GET_REM(x) (rem[x]) static const uint8_t rem[] = { 19, 19, 18, 14, 13, 11, 10, 8, 7, 6, 4, 3, 1, 0 }; unsigned int m; unsigned int d; unsigned int beef; unsigned int cake; /* get 32-adic doys */ m = (doy + 19) / 32U; d = (doy + 19) % 32U; beef = GET_REM(m); cake = GET_REM(m + 1); /* put leap years into cake */ if (UNLIKELY(__leapp(year) && cake < 16U)) { /* note how all leap-affected cakes are < 16 */ beef += beef < 16U; cake++; } if (d <= cake) { d = doy - ((m - 1) * 32 - 19 + beef); } else { d = doy - (m++ * 32 - 19 + cake); } return (struct __md_s){.m = m, .d = d}; #undef GET_REM } #elif defined GET_MD_TRIMESTER /* Trimester algo, we can't figure out which one's faster */ static __attribute__((const, pure)) struct __md_s __yday_get_md(unsigned int year, unsigned int yday) { /* The idea here is that the year can be divided into trimesters: * Mar 31 Aug 31 Jan 31 * Apr 30 Sep 30 Feb 28/29 * May 31 Oct 31 * Jun 30 Nov 30 * Jul 31 Dec 31 * * The first two trimesters have 153 days each, and given one of those * the m/d calculation is simply: * m,d <- yday divrem 30.5 * * where 30.5 is achieved by: * m,d <- 2 * yday divrem 61 * of course. * * Normally given the trimester and the m,d within the trimester you * could assemble the m,d of a gregorian year as: * m <- 5 * trimstr + m + 3 * d <- d * given 0-counting. And wrap around months 13 and 14 to 01 and 02; * so from this the subtrahend in the 2nd trimester case should be * 153 (as opposed to -30 now). * * We employ a simpler version here that ``inserts'' 2 days after February, * yday 60 is 29 Feb, yday 61 is 30 Feb, then proceed as per usual until * the end of July where another (unnamed) 30-day month is inserted that * goes seamlessly with the 31,30,31,30... cycle */ int m; int d; if ((yday -= 1 + __leapp(year)) < 59) { /* 3rd trimester */ yday += __leapp(year); } else if ((yday += 2) < 153 + 61) { /* 1st trimester */ ; } else { /* 2nd trimester */ yday += 30; } m = 2 * yday / 61; d = 2 * yday % 61; return (struct __md_s){.m = m + 1 - (m >= 7), .d = d / 2 + 1}; } #endif /* GET_MD_* */ static inline __attribute__((const, pure)) dt_dow_t __get_jan01_yday_dow(unsigned int yd, dt_dow_t w) { unsigned int res = (yd + 6U - (unsigned int)w) % GREG_DAYS_P_WEEK; return (dt_dow_t)(DT_SUNDAY - res); } static inline __attribute__((const, pure)) unsigned int __get_ydays(unsigned int y) { return LIKELY(!__leapp(y)) ? 365U : 366U; } DEFUN __attribute__((pure)) dt_yd_t __yd_fixup(dt_yd_t d) { int ydays; if (LIKELY(d.d <= 365)) { /* trivial */ ; } else if (d.d > (ydays = __get_ydays(d.y))) { d.d = ydays; } return d; } #endif /* YD_ASPECT_HELPERS_ */ #if defined ASPECT_GETTERS && !defined YD_ASPECT_GETTERS_ #define YD_ASPECT_GETTERS_ static inline __attribute__((const, pure)) int __get_isowk_wd(unsigned int yd, dt_dow_t f01) { /* given the weekday the year starts with, F01, and the year-day YD * return the iso week number */ static const int_fast8_t iso[] = {2, 1, 0, -1, -2, 4, 3, 2}; return (GREG_DAYS_P_WEEK + yd - iso[f01]) / GREG_DAYS_P_WEEK; } DEFUN __attribute__((const, pure)) int __yd_get_wcnt_abs(dt_yd_t d) { /* absolutely count the n-th occurrence of WD regardless what WD * the year started with */ int yd = d.d; /* express yd as 7k + n relative to jan01 */ return (GREG_DAYS_P_WEEK + yd - 1) / GREG_DAYS_P_WEEK; } DEFUN __attribute__((const, pure)) int __yd_get_wcnt_iso(dt_yd_t d) { /* like __yd_get_wcnt() but for iso week conventions * the week with the first thursday is the first week, * so a year starting on S is the first week, * a year starting on M is the first week * a year starting on T ... */ /* iso weeks always start on Mon */ unsigned int y = d.y; int yd = d.d; unsigned int y01 = __get_jan01_wday(y); int wk; /* express yd as 7k + n relative to jan01 */ wk = __get_isowk_wd(yd, (dt_dow_t)y01); if (UNLIKELY(wk < 1)) { /* get last years y01 * which is basically y01 - (365|366 % 7) */ if (LIKELY(!__leapp(--y))) { /* -= 1 */ y01 += 6; yd += 365; } else { /* -= 2 */ y01 += 5; yd += 366; } if (y01 > GREG_DAYS_P_WEEK) { y01 -= GREG_DAYS_P_WEEK; } /* same computation now */ wk = __get_isowk_wd(yd, (dt_dow_t)y01); } if (UNLIKELY(wk == 53)) { /* check next year's y01 */ if (LIKELY(!__leapp(y))) { y01 += 1; } else { /* -= 2 */ y01 += 2; } if (!(y01 == DT_FRIDAY || y01 == DT_SATURDAY)) { /* 53rd week is no more */ wk = 1; } } return wk; } DEFUN __attribute__((const, pure)) int __yd_get_wcnt(dt_yd_t d, dt_dow_t _1st_wd) { /* absolutely count the n-th occurrence of WD regardless what WD * the year started with */ unsigned int y = d.y; int yd = d.d; dt_dow_t y01 = __get_jan01_wday(y); int wk; /* yd of the FIRST week of the year */ if ((wk = 8 - (int)y01 + (int)_1st_wd) > 7) { wk -= 7; } /* and now express yd as 7k + n relative to jan01 */ return (yd - wk + 7) / 7; } static dt_dow_t __yd_get_wday(dt_yd_t this) { unsigned int j01_wd = __get_jan01_wday(this.y); if (LIKELY(j01_wd != DT_MIRACLEDAY && this.d)) { unsigned int wd = (this.d - 1 + j01_wd) % GREG_DAYS_P_WEEK; return (dt_dow_t)(wd ?: DT_SUNDAY); } return DT_MIRACLEDAY; } static struct __md_s __yd_get_md(dt_yd_t this) { return __yday_get_md(this.y, this.d); } #endif /* YD_ASPECT_GETTERS_ */ #if defined ASPECT_CONV && !defined YD_ASPECT_CONV_ #define YD_ASPECT_CONV_ /* we need some getter stuff, so get it */ #define ASPECT_GETTERS #include "yd.c" #undef ASPECT_GETTERS static dt_ymd_t __yd_to_ymd(dt_yd_t d) { struct __md_s md = __yd_get_md(d); #if defined HAVE_ANON_STRUCTS_INIT return (dt_ymd_t){.y = d.y, .m = md.m, .d = md.d}; #else /* !HAVE_ANON_STRUCTS_INIT */ dt_ymd_t res; res.y = d.y; res.m = md.m; res.d = md.d; return res; #endif /* HAVE_ANON_STRUCTS_INIT */ } static dt_daisy_t __yd_to_daisy(dt_yd_t d) { if (UNLIKELY((signed int)TO_BASE(d.y) < 0)) { return 0; } return __jan00_daisy(d.y) + d.d; } static dt_ymcw_t __yd_to_ymcw(dt_yd_t d) { struct __md_s md = __yd_get_md(d); unsigned int w = __yd_get_wday(d); unsigned int c; /* we obtain C from weekifying the month */ c = (md.d - 1U) / GREG_DAYS_P_WEEK + 1U; #if defined HAVE_ANON_STRUCTS_INIT return (dt_ymcw_t){.y = d.y, .m = md.m, .c = c, .w = w}; #else /* !HAVE_ANON_STRUCTS_INIT */ dt_ymcw_t res; res.y = d.y; res.m = md.m; res.c = c; res.w = w; return res; #endif /* HAVE_ANON_STRUCTS_INIT */ } static dt_ywd_t __yd_to_ywd(dt_yd_t d) { dt_dow_t w = __yd_get_wday(d); unsigned int c = __yd_get_wcnt_abs(d); return __make_ywd_c(d.y, c, w, YWD_ABSWK_CNT); } #endif /* ASPECT_CONV */ #if defined ASPECT_ADD && !defined YD_ASPECT_ADD_ #define YD_ASPECT_ADD_ static __attribute__((pure)) dt_yd_t __yd_fixup_d(unsigned int y, signed int d) { dt_yd_t res = {0}; if (LIKELY(d >= 1 && d <= 365)) { /* all years in our design range have at least 365 days */ ; } else if (d < 1) { int ydays; do { y--; ydays = __get_ydays(y); d += ydays; } while (d < 1); } else { int ydays; while (d > (ydays = __get_ydays(y))) { d -= ydays; y++; } } res.y = y; res.d = d; return res; } static dt_yd_t __yd_add_d(dt_yd_t d, int n) { /* add N days to D */ signed int tgtd = d.d + n; /* fixup the day */ return __yd_fixup_d(d.y, tgtd); } static dt_yd_t __yd_add_b(dt_yd_t d, int n) { /* add N business days to D */ dt_dow_t wd = __yd_get_wday(d); int tgtd = d.d + __get_d_equiv(wd, n); /* fixup the day, i.e. 2012-0367 -> 2013-001 */ return __yd_fixup_d(d.y, tgtd); } static dt_yd_t __yd_add_w(dt_yd_t d, int n) { /* add N weeks to D */ return __yd_add_d(d, GREG_DAYS_P_WEEK * n); } static dt_yd_t __yd_add_y(dt_yd_t d, int n) { /* add N years to D */ d.y += n; return d; } #endif /* ASPECT_ADD */ #if defined ASPECT_DIFF && !defined YD_ASPECT_DIFF_ #define YD_ASPECT_DIFF_ static __attribute__((const, pure)) struct dt_ddur_s __yd_diff(dt_yd_t d1, dt_yd_t d2) { /* compute d2 - d1 entirely in terms of ymd but express the result as yd */ struct dt_ddur_s res = dt_make_ddur(DT_DURYD, 0); signed int tgtd; signed int tgty; if (d1.u > d2.u) { /* swap d1 and d2 */ dt_yd_t tmp = d1; res.neg = 1; d1 = d2; d2 = tmp; } /* first compute the difference in years */ tgty = (d2.y - d1.y); /* ... and days */ tgtd = (d2.d - d1.d); /* add leap corrections, this is actually a matrix * ({L,N}x{B,A})^2, Leap/Non-leap, Before/After leap day */ if (UNLIKELY(__leapp(d1.y)) && LIKELY(d1.d >= 60)) { /* LA?? */ if (UNLIKELY(d1.d == 60)) { /* corner case, treat 29 Feb as 01 Mar */ ; } else if (!__leapp(d2.y)) { /* LAN? */ tgtd++; } else if (d2.d < 60) { /* LALB */ tgtd++; } } else if (d1.d >= 60 && UNLIKELY(__leapp(d2.y)) && d2.d >= 60) { /* NALA */ tgtd--; } /* add carry */ if (tgtd < 0) { tgty--; tgtd += 365 + ((__leapp(d2.y)) && d2.d >= 60); } /* fill in the results */ res.yd.y = tgty; res.yd.d = tgtd; return res; } #endif /* ASPECT_DIFF */ #undef ASPECT_YD /* yd.c ends here */ dateutils-0.4.5/lib/ymcw.c000066400000000000000000000332011335042257000154070ustar00rootroot00000000000000/*** ymcw.c -- guts for ymcw dates * * Copyright (C) 2010-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of dateutils. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * **/ #define ASPECT_YMCW #if !defined DEFUN # define DEFUN #endif /* !DEFUN */ #if !defined YMCW_ASPECT_HELPERS_ #define YMCW_ASPECT_HELPERS_ static __attribute__((pure)) unsigned int __get_mcnt(unsigned int y, unsigned int m, dt_dow_t w) { /* get the number of weekdays W in Y-M, which is the max count * for a weekday W in ymcw dates in year Y and month M */ dt_dow_t wd01 = __get_m01_wday(y, m); unsigned int md = __get_mdays(y, m); /* the maximum number of WD01s in Y-M */ unsigned int wd01cnt = (md - 1) / GREG_DAYS_P_WEEK + 1; /* modulus */ unsigned int wd01mod = (md - 1) % GREG_DAYS_P_WEEK; /* now the next WD01MOD days also have WD01CNT occurrences * if wd01 + wd01mod exceeds the DAYS_PER_WEEK barrier wrap * around by extending W to W + DAYS_PER_WEEK */ if ((w >= wd01 && w <= wd01 + wd01mod) || (w + GREG_DAYS_P_WEEK) <= wd01 + wd01mod) { return wd01cnt; } else { return wd01cnt - 1; } } DEFUN dt_ymcw_t __ymcw_fixup(dt_ymcw_t d) { /* given dates like 2012-02-05-01 this returns 2012-02-04-01 */ int mc; if (LIKELY(d.c <= 4)) { /* every month has 4 occurrences of any weekday */ ; } else if (d.m == 0 || d.w == DT_MIRACLEDAY) { /* um */ ; } else if (d.c > (mc = __get_mcnt(d.y, d.m, (dt_dow_t)d.w))) { d.c = mc; } return d; } #endif /* YMCW_ASPECT_HELPERS_ */ #if defined ASPECT_GETTERS && !defined YMCW_ASPECT_GETTERS_ #define YMCW_ASPECT_GETTERS_ static dt_dow_t __ymcw_get_wday(dt_ymcw_t that) { return (dt_dow_t)(that.w ?: DT_SUNDAY); } DEFUN unsigned int __ymcw_get_yday(dt_ymcw_t that) { /* return the N-th W-day in Y, this is equivalent with 8601's Y-W-D calendar * where W is the week of the year and D the day in the week */ /* if a year starts on W, then it's * 5 Ws in jan * 4 Ws in feb * 4 Ws in mar * 5 Ws in apr * 4 Ws in may * 4 Ws in jun * 5 Ws in jul * 4 Ws in aug * 4 + leap Ws in sep * 5 - leap Ws in oct * 4 Ws in nov * 5 Ws in dec, * so go back to the last W, and compute its number instead * * Here's the full schema: * For W+0 * 5 4 4 5 4 4 5 4 4 5 4 5 non-leap * 5 4 4 5 4 4 5 4 5 4 4 5 leap flip9 * * For W+1 * 5 4 4 4 5 4 5 4 4 5 4 4 non-leap * 5 4 4 5 4 4 5 4 4 5 4 5 leap flip4 flip12 * * For W+2 * 5 4 4 4 5 4 4 5 4 5 4 4 non-leap * 5 4 4 4 5 4 5 4 4 5 4 4 leap flip7 * * For W+3 * 4 4 5 4 5 4 4 5 4 4 5 4 non-leap * 4 5 4 4 5 4 4 5 4 5 4 4 leap flip2 flip10 * * For W+4 * 4 4 5 4 4 5 4 5 4 4 5 4 non-leap * 4 4 5 4 5 4 4 5 4 4 5 4 leap flip5 * * For W+5 * 4 4 5 4 4 5 4 4 5 4 4 5 non-leap * 4 4 5 4 4 5 4 5 4 4 5 4 leap flip8 flip11 * * For W+6 * 4 4 4 5 4 4 5 4 5 4 4 5 non-leap * 4 4 5 4 4 5 4 4 5 4 4 5 leap flip3 flip6 * * flipN denotes which month in a leap year becomes 5 where the * month in the non-leap year equivalent has value 4. * * The flips for W+1 W+2, W+4, W+5, W+6 can be presented through * non-leap rules: * * 544544544545544544544545 * 544544545445544544545445 * * 544454544544544454544544 * 544544544545544544544545 = non-leap W+0 * * 544454454544544454454544 * 544454544544544454544544 = non-leap W+1 * * 445454454454445454454454 * 454454454544454454454544 * * 445445454454445445454454 * 445454454454445454454454 = non-leap W+3 * * 445445445445445445445445 * 445445454454445445454454 = non-leap W+4 * * 444544545445444544545445 * 445445445445445445445445 = non-leap W+5 */ static uint8_t ycum[][12] = { { /* W+0 */ 0, 5, 9, 13, 18, 22, 26, 31, 35, 39, 44, 48, /*53*/ }, { /* W+1 */ 0, 5, 9, 13, 17, 22, 26, 31, 35, 39, 44, 48, /*52*/ }, { /* W+2 */ 0, 5, 9, 13, 17, 22, 26, 30, 35, 39, 44, 48, /*52*/ }, { /* W+3 */ 0, 4, 8, 13, 17, 22, 26, 30, 35, 39, 43, 48, /*52*/ }, { /* W+4 */ 0, 4, 8, 13, 17, 21, 26, 30, 35, 39, 43, 48, /*52*/ }, { /* W+5 */ 0, 4, 8, 13, 17, 21, 26, 30, 34, 39, 43, 47, /*52*/ }, { /* W+6 */ 0, 4, 8, 12, 17, 21, 25, 30, 34, 39, 43, 47, /*52*/ }, { /* leap-year rule W+0 */ 0, 5, 9, 13, 18, 22, 26, 31, 35, 40, 44, 48, /*53*/ /* leap-year rule W+3 = W+0 + 1mo + 4 */ }, }; dt_dow_t j01w = __get_jan01_wday(that.y); unsigned int diff = j01w <= that.w ? that.w - j01w : that.w + 7 - j01w; if (UNLIKELY(__leapp(that.y))) { switch (diff) { case 3: if (UNLIKELY(that.m < 2)) { return that.c; } return that.c + (ycum[7])[that.m - 2] + 4; case 0: return that.c + (ycum[7])[that.m - 1]; default: case 1: case 2: case 4: case 5: case 6: diff--; break; } } return that.c + (ycum[diff])[that.m - 1]; } static unsigned int __ymcw_get_mday(dt_ymcw_t that) { unsigned int wd01; unsigned int res; /* see what weekday the first of the month was*/ wd01 = __get_m01_wday(that.y, that.m); /* first WD1 is 1, second WD1 is 8, third WD1 is 15, etc. * so the first WDx with WDx > WD1 is on (WDx - WD1) + 1 */ res = (that.w + GREG_DAYS_P_WEEK - wd01) % GREG_DAYS_P_WEEK + 1; res += GREG_DAYS_P_WEEK * (that.c - 1); /* not all months have a 5th X, so check for this */ if (res > __get_mdays(that.y, that.m)) { /* 5th = 4th in that case */ res -= GREG_DAYS_P_WEEK; } return res; } static int __ymcw_get_bday(dt_ymcw_t that, dt_bizda_param_t bp) { dt_dow_t wd01; int res; switch (that.w) { case DT_SUNDAY: case DT_SATURDAY: return -1; default: break; } if (bp.ab != BIZDA_AFTER || bp.ref != BIZDA_ULTIMO) { /* no support yet */ return -1; } /* weekday the month started with */ wd01 = __get_m01_wday(that.y, that.m); res = (signed int)(that.w - wd01) + DUWW_BDAYS_P_WEEK * (that.c) + 1; return res; } #endif /* YMCW_ASPECT_GETTERS_ */ #if defined ASPECT_CONV && !defined YMCW_ASPECT_CONV_ #define YMCW_ASPECT_CONV_ /* we need some getter stuff, so get it */ #define ASPECT_GETTERS #include "ymcw.c" #undef ASPECT_GETTERS static dt_ymd_t __ymcw_to_ymd(dt_ymcw_t d) { unsigned int md = __ymcw_get_mday(d); #if defined HAVE_ANON_STRUCTS_INIT return (dt_ymd_t){.y = d.y, .m = d.m, .d = md}; #else /* !HAVE_ANON_STRUCTS_INIT */ dt_ymd_t res; res.y = d.y; res.m = d.m; res.d = md; return res; #endif /* HAVE_ANON_STRUCTS_INIT */ } static dt_ywd_t __ymcw_to_ywd(dt_ymcw_t d) { unsigned int y = d.y; dt_dow_t w = (dt_dow_t)d.w; unsigned int c = __ymcw_get_yday(d); return __make_ywd_c(y, c, w, YWD_ABSWK_CNT); } static dt_daisy_t __ymcw_to_daisy(dt_ymcw_t d) { dt_daisy_t res; unsigned int sy = d.y; unsigned int sm = d.m; unsigned int sd; if (UNLIKELY((signed int)TO_BASE(sy) < 0)) { return 0; } sd = __ymcw_get_mday(d); res = __jan00_daisy(sy); res += __md_get_yday(sy, sm, sd); return res; } static dt_yd_t __ymcw_to_yd(dt_ymcw_t d) { unsigned int sd = __ymcw_get_mday(d); unsigned int sm = d.m; unsigned int sy = d.y; #if defined HAVE_ANON_STRUCTS_INIT return (dt_yd_t){.y = sy, .d = __md_get_yday(sy, sm, sd)}; #else dt_yd_t res; res.y = sy; res.d = __md_get_yday(sy, sm, sd); return res; #endif } #endif /* ASPECT_CONV */ #if defined ASPECT_ADD && !defined YMCW_ASPECT_ADD_ #define YMCW_ASPECT_ADD_ static dt_ymcw_t __ymcw_fixup_c(unsigned int y, signed int m, signed int c, dt_dow_t w) { dt_ymcw_t res = {0}; /* fixup q */ if (LIKELY(c >= 1 && c <= 4)) { /* all months in our design range have 4 occurrences of * any weekday, so YAAAY*/ ; } else if (c < 1) { int mc; do { if (UNLIKELY(--m < 1)) { --y; m = GREG_MONTHS_P_YEAR; } mc = __get_mcnt(y, m, w); c += mc; } while (c < 1); } else { int mc; while (c > (mc = __get_mcnt(y, m, w))) { c -= mc; if (UNLIKELY(++m > (signed int)GREG_MONTHS_P_YEAR)) { ++y; m = 1; } } } /* final assignment */ res.y = y; res.m = m; res.c = c; res.w = w; return res; } static dt_ymcw_t __ymcw_add_w(dt_ymcw_t d, int n) { /* add N weeks to D */ signed int tgtc = d.c + n; return __ymcw_fixup_c(d.y, d.m, tgtc, (dt_dow_t)d.w); } static dt_ymcw_t __ymcw_add_d(dt_ymcw_t d, int n) { /* add N days to D * we reduce this to __ymcw_add_w() */ signed int aw = n / (signed int)GREG_DAYS_P_WEEK; signed int ad = n % (signed int)GREG_DAYS_P_WEEK; if ((ad += d.w) >= (signed int)GREG_DAYS_P_WEEK) { ad -= GREG_DAYS_P_WEEK; aw++; } else if (ad < 0) { ad += GREG_DAYS_P_WEEK; aw--; } /* fixup for abswk count, m01 may be any wd */ { dt_dow_t m01 = __get_m01_wday(d.y, d.m); if ((dt_dow_t)d.w < m01 && (dt_dow_t)ad >= m01) { aw++; } else if ((dt_dow_t)d.w >= m01 && (dt_dow_t)ad < m01) { aw--; } } d.w = (dt_dow_t)ad; return __ymcw_add_w(d, aw); } static dt_ymcw_t __ymcw_add_b(dt_ymcw_t d, int n) { /* add N business days to D */ #if 0 /* trivial trait, reduce to _add_d() problem and dispatch */ dt_dow_t wd = __ymcw_get_wday(d); return __ymcw_add_d(d, __get_d_equiv(wd, n)); #else signed int aw = n / (signed int)DUWW_BDAYS_P_WEEK; signed int ad = n % (signed int)DUWW_BDAYS_P_WEEK; if ((ad += d.w) > (signed int)DUWW_BDAYS_P_WEEK) { ad -= DUWW_BDAYS_P_WEEK; aw++; } else if (ad <= 0) { ad += DUWW_BDAYS_P_WEEK; aw--; } /* fixup for abswk count, m01 may be any wd */ { dt_dow_t m01 = __get_m01_wday(d.y, d.m); if ((dt_dow_t)d.w < m01 && (dt_dow_t)ad >= m01) { aw++; } else if ((dt_dow_t)d.w >= m01 && (dt_dow_t)ad < m01) { aw--; } } d.w = (dt_dow_t)ad; return __ymcw_add_w(d, aw); #endif } static dt_ymcw_t __ymcw_add_m(dt_ymcw_t d, int n) { /* add N months to D */ signed int tgtm = d.m + n; while (tgtm > (signed int)GREG_MONTHS_P_YEAR) { tgtm -= GREG_MONTHS_P_YEAR; ++d.y; } while (tgtm < 1) { tgtm += GREG_MONTHS_P_YEAR; --d.y; } /* final assignment */ d.m = tgtm; return d; } static dt_ymcw_t __ymcw_add_y(dt_ymcw_t d, int n) { /* add N years to D */ d.y += n; return d; } #endif /* ASPECT_ADD */ #if defined ASPECT_DIFF && !defined YMCW_ASPECT_DIFF_ #define YMCW_ASPECT_DIFF_ static struct dt_ddur_s __ymcw_diff(dt_ymcw_t d1, dt_ymcw_t d2) { /* compute d2 - d1 entirely in terms of ymd */ struct dt_ddur_s res = dt_make_ddur(DT_DURYMCW, 0); signed int tgtd; signed int tgtm; dt_dow_t wd01, wd02; if (__ymcw_cmp(d1, d2) > 0) { dt_ymcw_t tmp = d1; d1 = d2; d2 = tmp; res.neg = 1; } wd01 = __get_m01_wday(d1.y, d1.m); if (d2.y != d1.y || d2.m != d1.m) { wd02 = __get_m01_wday(d2.y, d2.m); } else { wd02 = wd01; } /* first compute the difference in months Y2-M2-01 - Y1-M1-01 */ tgtm = GREG_MONTHS_P_YEAR * (d2.y - d1.y) + (d2.m - d1.m); /* using the firsts of the month WD01, represent d1 and d2 as * the C-th WD01 plus OFF */ { unsigned int off1; unsigned int off2; off1 = __uimod(d1.w - wd01, GREG_DAYS_P_WEEK); off2 = __uimod(d2.w - wd02, GREG_DAYS_P_WEEK); tgtd = off2 - off1 + GREG_DAYS_P_WEEK * (d2.c - d1.c); } /* fixups */ if (tgtd < (signed int)GREG_DAYS_P_WEEK && tgtm > 0) { /* if tgtm is 0 it remains 0 and tgtd remains negative */ /* get the target month's mdays */ unsigned int d2m = d2.m; unsigned int d2y = d2.y; if (--d2m < 1) { d2m = GREG_MONTHS_P_YEAR; d2y--; } tgtd += __get_mdays(d2y, d2m); tgtm--; } /* fill in the results */ res.ymcw.y = tgtm / GREG_MONTHS_P_YEAR; res.ymcw.m = tgtm % GREG_MONTHS_P_YEAR; res.ymcw.c = tgtd / GREG_DAYS_P_WEEK; res.ymcw.w = tgtd % GREG_DAYS_P_WEEK; return res; } #endif /* ASPECT_DIFF */ #if defined ASPECT_CMP && !defined YMCW_ASPECT_CMP_ #define YMCW_ASPECT_CMP_ DEFUN int __ymcw_cmp(dt_ymcw_t d1, dt_ymcw_t d2) { if (d1.y < d2.y) { return -1; } else if (d1.y > d2.y) { return 1; } else if (d1.m < d2.m) { return -1; } else if (d1.m > d2.m) { return 1; } /* we're down to counts, however, the last W of a month is always * count 5, even though counting forward it would be 4 */ if (d1.c < d2.c) { return -1; } else if (d1.c > d2.c) { return 1; } /* now it's up to the first of the month */ { dt_dow_t wd01; unsigned int off1; unsigned int off2; wd01 = __get_m01_wday(d1.y, d1.m); /* represent cw as C-th WD01 + OFF */ off1 = __uimod(d1.w - wd01, GREG_DAYS_P_WEEK); off2 = __uimod(d2.w - wd01, GREG_DAYS_P_WEEK); if (off1 < off2) { return -1; } else if (off1 > off2) { return 1; } else { return 0; } } } #endif /* ASPECT_CMP */ #if defined ASPECT_STRF && !defined YMCW_ASPECT_STRF_ #define YMCW_ASPECT_STRF_ #endif /* ASPECT_STRF */ /* ymcw.c ends here */ dateutils-0.4.5/lib/ymd.c000066400000000000000000000402241335042257000152240ustar00rootroot00000000000000/*** ymd.c -- guts for ymd dates * * Copyright (C) 2010-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of dateutils. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * **/ /* set aspect temporarily */ #define ASPECT_YMD /* permanent aspect, to be read as have we ever seen aspect_ymd */ #if !defined ASPECT_YMD_ #define ASPECT_YMD_ #endif /* !ASPECT_YMD_ */ #include "nifty.h" /* some algorithmic choices */ #if defined YMD_GET_WDAY_LOOKUP #elif defined YMD_GET_WDAY_ZELLER #elif defined YMD_GET_WDAY_SAKAMOTO #elif defined YMD_GET_WDAY_7YM_ALL #elif defined YMD_GET_WDAY_7YM_REP #else /* default algo */ # define YMD_GET_WDAY_LOOKUP #endif #if !defined DEFUN # define DEFUN #endif /* !DEFUN */ #if !defined YMD_ASPECT_HELPERS_ #define YMD_ASPECT_HELPERS_ DEFUN __attribute__((pure)) inline unsigned int __get_mdays(unsigned int y, unsigned int m) { /* get the number of days in Y-M */ unsigned int res; if (UNLIKELY(m < 1 || m > GREG_MONTHS_P_YEAR)) { return 0; } /* use our cumulative yday array */ res = __md_get_yday(y, m + 1, 0); return res - __md_get_yday(y, m, 0); } DEFUN __attribute__((pure)) dt_ymd_t __ymd_fixup(dt_ymd_t d) { /* given dates like 2012-02-32 this returns 2012-02-29 */ int mdays; if (LIKELY(d.d <= 28)) { /* every month has 28 days in our range */ ; } else if (UNLIKELY(d.m == 0 || d.m > GREG_MONTHS_P_YEAR)) { ; } else if (d.d > (mdays = __get_mdays(d.y, d.m))) { d.d = mdays; } return d; } static dt_dow_t __get_m01_wday(unsigned int year, unsigned int mon) { /* get the weekday of the first of MONTH in YEAR */ unsigned int off; dt_dow_t cand; if (UNLIKELY(mon < 1 || mon > GREG_MONTHS_P_YEAR)) { return DT_MIRACLEDAY; } cand = __get_jan01_wday(year); off = __md_get_yday(year, mon, 0); off = (cand + off) % GREG_DAYS_P_WEEK; return (dt_dow_t)(off ?: DT_SUNDAY); } #if defined YMD_GET_WDAY_LOOKUP /* lookup version */ static dt_dow_t __get_dom_wday(unsigned int year, unsigned int mon, unsigned int dom) { unsigned int yd; unsigned int j01_wd; if ((yd = __md_get_yday(year, mon, dom)) > 0 && (j01_wd = __get_jan01_wday(year)) != DT_MIRACLEDAY) { unsigned int wd = (yd - 1 + j01_wd) % GREG_DAYS_P_WEEK; return (dt_dow_t)(wd ?: DT_SUNDAY); } return DT_MIRACLEDAY; } #elif defined YMD_GET_WDAY_ZELLER /* Zeller algorithm */ static dt_dow_t __get_dom_wday(int year, int mon, int dom) { /* this is Zeller's method, but there's a problem when we use this for * the bizda calendar. */ int w; int c, x; int d, y; unsigned int wd; if ((mon -= 2) <= 0) { mon += 12; year--; } d = year / 100; c = year % 100; x = c / 4; y = d / 4; w = (13 * mon - 1) / 5; wd = (w + x + y + dom + c - 2 * d) % GREG_DAYS_P_WEEK; return (dt_dow_t)(wd ?: DT_SUNDAY); } #elif defined YMD_GET_WDAY_SAKAMOTO /* Sakamoto method */ static dt_dow_t __get_dom_wday(int year, int mon, int dom) { static int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4}; int res; unsigned int wd; year -= mon < 3; res = year + year / 4 - year / 100 + year / 400; res += t[mon - 1] + dom; wd = (unsigned int)res % GREG_DAYS_P_WEEK; return (dt_dow_t)(wd ?: DT_SUNDAY); } #elif defined YMD_GET_WDAY_7YM_ALL || defined YMD_GET_WDAY_7YM_REP /* this one's work in progress * first observe the 7 patterns in months FG and H..Z and how leap years * correspond to ordinary years. * * Use: * dseq 1917-01-01 1mo 2417-12-01 -f '%Y %m %_a' | \ * awk 'BEGIN{FS=" "} \ * {a[$1] = "" a[$1] "" ($2=="03" ? " " : "") "" $3;} \ * END{for (i in a) print(i "\t" a[i]);}' | \ * sort | sort -k3 -k2 -u * * for instance to get this table (months FG and months H..Z): * 1924 TF ATRSTFMWAM * 1919 WA ATRSTFMWAM * 1940 MR FMWAMRSTFS * 1918 TF FMWAMRSTFS * 1926 FM MRATRSWFMW * 1920 RS MRATRSWFMW * 1917 MR RSTFSWAMRA * 1928 SW RSTFSWAMRA * 1925 RS SWFMWATRST * 1936 WA SWFMWATRST * 1921 AT TFSWFMRATR * 1932 FM TFSWFMRATR * 1944 AT WAMRATFSWF * 1922 SW WAMRATFSWF * * and note how leap years and ordinary years pair up. * * After a bit of number crunching (consider all years mod 28) we'll find: * H..Z * 0 -> 6 -> 17 -> 23 * 4 -> 10 -> 21 -> 27 * 8 -> 14 -> 25 -> 3 * 12 -> 18 -> 1 -> 7 * 16 -> 22 -> 5 -> 11 * 20 -> 26 -> 9 -> 15 * 24 -> 2 -> 13 -> 19 * * where obviously the FG years are a permutation (13 14 15 21 22 17 18)^-1 * of the H..Z years. * * It's quite easy to see how this system forms an orbit through C28 via: * * [0]C4 + 0 = [4]C4 + 1 = [1]C4 + 2 = [5]C4 + 3 * [1]C4 + 0 = [5]C4 + 1 = [2]C4 + 2 = [6]C4 + 3 * [2]C4 + 0 = [6]C4 + 1 = [3]C4 + 2 = [0]C4 + 3 * [3]C4 + 0 = [0]C4 + 1 = [4]C4 + 2 = [1]C4 + 3 * [4]C4 + 0 = [1]C4 + 1 = [5]C4 + 2 = [2]C4 + 3 * [5]C4 + 0 = [2]C4 + 1 = [6]C4 + 2 = [3]C4 + 3 * [6]C4 + 0 = [3]C4 + 1 = [0]C4 + 2 = [4]C4 + 3 * * and so by decomposing a year mod 28 and into C7*C4 we can map it to the * weekday. * * Here's the algo: * input: year * output: idx, weekday series index for H.. * * year <- year mod 28 * x,y <- decompose year as [x]C4 + y * idx <- x - 0, if y = 0 * x - 4, if y = 1 * x - 1, if y = 2 * x - 5, if y = 3 * * Proceed similar for FG series. * That's how the formulas below came into being. * * For the shortened version (REP for representant) you have observe * that from leap year to leap year the weekday difference for each * respective month is 5. */ static unsigned int __get_widx_H(unsigned int y) { /* return the equivalence class number for H.. weekdays for year Y. */ static unsigned int add[] = {0, 3, 6, 2}; unsigned int idx, res; y = y % 28U; idx = y / 4U; res = y % 4U; return (idx + add[res]) % GREG_DAYS_P_WEEK; } static unsigned int __get_widx_FG(unsigned int y) { /* return the equivalence class number for FG weekdays for year Y. */ static unsigned int add[] = {0, 6, 2, 5}; unsigned int idx, res; y = y % 28U; idx = y / 4U; res = y % 4U; return (idx + add[res]) % GREG_DAYS_P_WEEK; } #if !defined WITH_FAST_ARITH static inline __attribute__((pure)) unsigned int __get_28y_year_equiv_H(unsigned year) { /* like __get_28y_year_equiv() but for months H..Z * needed for 7YM algo */ year = year % 400U; if (year >= 300U) { return year + 1600U; } else if (year >= 200U) { return year + 1724U; } else if (year >= 100U) { return year + 1820U; } return year + 2000; } #endif /* !WITH_FAST_ARITH */ #if defined YMD_GET_WDAY_7YM_ALL static inline __attribute__((pure)) unsigned int __get_ser(unsigned int class, unsigned int mon) { # define M (DT_MONDAY) # define T (DT_TUESDAY) # define W (DT_WEDNESDAY) # define R (DT_THURSDAY) # define F (DT_FRIDAY) # define A (DT_SATURDAY) # define S (DT_SUNDAY) static uint8_t ser[][12] = { { /* 1932 = [[0]C4 + 0]C28 */ F, M, T, F, S, W, F, M, R, A, T, R, }, { /* 1936 = [[1]C4 + 0]C28 */ W, A, S, W, F, M, W, A, T, R, S, T, }, { /* 1940 = [[2]C4 + 0]C28 */ M, R, F, M, W, A, M, R, S, T, F, S, }, { /* 1944 = [[3]C4 + 0]C28 */ A, T, W, A, M, R, A, T, F, S, W, F, }, { /* 1920 = [[4]C4 + 0]C28 */ R, S, M, R, A, T, R, S, W, F, M, W, }, { /* 1924 = [[5]C4 + 0]C28 */ T, F, A, T, R, S, T, F, M, W, A, M, }, { /* 1928 = [[6]C4 + 0]C28 */ S, W, R, S, T, F, S, W, A, M, R, A, }, }; # undef M # undef T # undef W # undef R # undef F # undef A # undef S return ser[class][mon]; } #elif defined YMD_GET_WDAY_7YM_REP static inline __attribute__((pure)) unsigned int __get_ser(unsigned int class, unsigned int mon) { # define M (DT_MONDAY) # define T (DT_TUESDAY) # define W (DT_WEDNESDAY) # define R (DT_THURSDAY) # define F (DT_FRIDAY) # define A (DT_SATURDAY) # define S (DT_SUNDAY) static unsigned int ser[12] = { /* 1932 = [[0]C4 + 0]C28 */ F, M, T, F, S, W, F, M, R, A, T, R, }; # undef M # undef T # undef W # undef R # undef F # undef A # undef S return ser[mon] + 5 * class; } #endif /* 7YM_ALL | 7YM_RES */ static dt_dow_t __get_dom_wday(unsigned int year, unsigned int mon, unsigned int dom) { unsigned int bm = mon - 1; unsigned int bd = dom - 1; unsigned int idx; unsigned int wd; if (bm < 2U) { /* FG */ #if defined WITH_FAST_ARITH unsigned int by = year; #else /* !WITH_FAST_ARITH */ unsigned int by = __get_28y_year_equiv(year); #endif /* !WITH_FAST_ARITH */ idx = __get_widx_FG(by); } else { #if defined WITH_FAST_ARITH unsigned int by = year; #else /* !WITH_FAST_ARITH */ unsigned int by = __get_28y_year_equiv_H(year); #endif /* !WITH_FAST_ARITH */ idx = __get_widx_H(by); } wd = (__get_ser(idx, bm) + bd) % GREG_DAYS_P_WEEK; return (dt_dow_t)(wd ?: DT_SUNDAY); } #endif /* 0 */ /* try to get helpers like __get_d_equiv() et al */ #include "bizda.c" #endif /* YMD_ASPECT_HELPERS_ */ #if defined ASPECT_GETTERS && !defined YMD_ASPECT_GETTERS_ #define YMD_ASPECT_GETTERS_ static unsigned int __ymd_get_yday(dt_ymd_t that) { unsigned int res; if (UNLIKELY(that.y == 0 || that.m == 0 || that.m > GREG_MONTHS_P_YEAR)) { return 0; } /* process */ res = __md_get_yday(that.y, that.m, that.d); return res; } static dt_dow_t __ymd_get_wday(dt_ymd_t that) { return __get_dom_wday(that.y, that.m, that.d); } DEFUN unsigned int __ymd_get_count(dt_ymd_t that) { /* get N where N is the N-th occurrence of wday in the month of that year */ #if 0 /* this proves to be a disaster when comparing ymcw dates */ if (UNLIKELY(that.d + GREG_DAYS_P_WEEK > __get_mdays(that.y, that.m))) { return 5; } #endif return (that.d - 1U) / GREG_DAYS_P_WEEK + 1U; } static int __ymd_get_wcnt_abs(dt_ymd_t d) { /* absolutely count the n-th occurrence of WD regardless what WD * the year started with * generally the path ymd->yd->get_wcnt_abs() is preferred */ int yd = __ymd_get_yday(d); /* and now express yd as 7k + n relative to jan01 */ return (yd - 1) / 7 + 1; } static int __ymd_get_bday(dt_ymd_t that, dt_bizda_param_t bp) { dt_dow_t wdd; if (bp.ab != BIZDA_AFTER || bp.ref != BIZDA_ULTIMO) { /* no support yet */ return -1; } /* weekday the month started with */ switch ((wdd = __ymd_get_wday(that))) { case DT_SUNDAY: case DT_SATURDAY: return -1; case DT_MONDAY: case DT_TUESDAY: case DT_WEDNESDAY: case DT_THURSDAY: case DT_FRIDAY: case DT_MIRACLEDAY: default: break; } /* get the number of business days between 1 and that.d */ return __get_nbdays(that.d, wdd); } #endif /* YMD_ASPECT_GETTERS_ */ #if defined ASPECT_CONV && !defined YMD_ASPECT_CONV_ #define YMD_ASPECT_CONV_ /* we need some getter stuff, so get it */ #define ASPECT_GETTERS #include "ymd.c" #undef ASPECT_GETTERS static dt_ymcw_t __ymd_to_ymcw(dt_ymd_t d) { unsigned int c = __ymd_get_count(d); unsigned int w = __ymd_get_wday(d); #if defined HAVE_ANON_STRUCTS_INIT return (dt_ymcw_t){.y = d.y, .m = d.m, .c = c, .w = w}; #else dt_ymcw_t res; res.y = d.y; res.m = d.m; res.c = c; res.w = w; return res; #endif } static dt_ywd_t __ymd_to_ywd(dt_ymd_t d) { dt_dow_t w = __ymd_get_wday(d); unsigned int c = __ymd_get_wcnt_abs(d); return __make_ywd_c(d.y, c, w, YWD_ABSWK_CNT); } static dt_daisy_t __ymd_to_daisy(dt_ymd_t d) { dt_daisy_t res; unsigned int sy = d.y; unsigned int sm = d.m; unsigned int sd; if (UNLIKELY((signed int)TO_BASE(sy) < 0)) { return 0; } #if !defined WITH_FAST_ARITH || defined OMIT_FIXUPS /* the non-fast arith has done the fixup already */ sd = d.d; #else /* WITH_FAST_ARITH && !OMIT_FIXUPS */ { unsigned int tmp = __get_mdays(sy, sm); if (UNLIKELY((sd = d.m) > tmp)) { sd = tmp; } } #endif /* !WITH_FAST_ARITH || OMIT_FIXUPS */ res = __jan00_daisy(sy); res += __md_get_yday(sy, sm, sd); return res; } static dt_yd_t __ymd_to_yd(dt_ymd_t d) { int yd = __ymd_get_yday(d); #if defined HAVE_ANON_STRUCTS_INIT return (dt_yd_t){.y = d.y, .d = yd}; #else dt_yd_t res; res.y = d.y; res.d = yd; return res; #endif } #endif /* ASPECT_CONV */ #if defined ASPECT_ADD && !defined YMD_ASPECT_ADD_ #define YMD_ASPECT_ADD_ static __attribute__((pure)) dt_ymd_t __ymd_fixup_d(unsigned int y, signed int m, signed int d) { dt_ymd_t res = {0}; if (LIKELY(d >= 1 && d <= 28)) { /* all months in our design range have at least 28 days */ ; } else if (d < 1) { int mdays; do { if (UNLIKELY(--m < 1)) { --y; m = GREG_MONTHS_P_YEAR; } mdays = __get_mdays(y, m); d += mdays; } while (d < 1); } else { int mdays; while (d > (mdays = __get_mdays(y, m))) { d -= mdays; if (UNLIKELY(++m > (signed int)GREG_MONTHS_P_YEAR)) { ++y; m = 1; } } } res.y = y; res.m = m; res.d = d; return res; } static dt_ymd_t __ymd_add_d(dt_ymd_t d, int n) { /* add N days to D */ signed int tgtd = d.d + n; /* fixup the day */ return __ymd_fixup_d(d.y, d.m, tgtd); } static dt_ymd_t __ymd_add_b(dt_ymd_t d, int n) { /* add N business days to D */ dt_dow_t wd = __ymd_get_wday(d); int tgtd = d.d + __get_d_equiv(wd, n); /* fixup the day, i.e. 2012-01-34 -> 2012-02-03 */ return __ymd_fixup_d(d.y, d.m, tgtd); } static dt_ymd_t __ymd_add_w(dt_ymd_t d, int n) { /* add N weeks to D */ return __ymd_add_d(d, GREG_DAYS_P_WEEK * n); } static dt_ymd_t __ymd_add_m(dt_ymd_t d, int n) { /* add N months to D */ signed int tgtm = d.m + n; while (tgtm > (signed int)GREG_MONTHS_P_YEAR) { tgtm -= GREG_MONTHS_P_YEAR; ++d.y; } while (tgtm < 1) { tgtm += GREG_MONTHS_P_YEAR; --d.y; } /* final assignment */ d.m = tgtm; return d; } static dt_ymd_t __ymd_add_y(dt_ymd_t d, int n) { /* add N years to D */ d.y += n; return d; } #endif /* ASPECT_ADD */ #if defined ASPECT_DIFF && !defined YMD_ASPECT_DIFF_ #define YMD_ASPECT_DIFF_ static struct dt_ddur_s __ymd_diff(dt_ymd_t d1, dt_ymd_t d2) { /* compute d2 - d1 entirely in terms of ymd */ struct dt_ddur_s res = dt_make_ddur(DT_DURYMD, 0); signed int tgtd; signed int tgtm; if (d1.u > d2.u) { /* swap d1 and d2 */ dt_ymd_t tmp = d1; res.neg = 1; d1 = d2; d2 = tmp; } /* first compute the difference in months Y2-M2-01 - Y1-M1-01 */ tgtm = GREG_MONTHS_P_YEAR * (d2.y - d1.y) + (d2.m - d1.m); if ((tgtd = d2.d - d1.d) < 0 && tgtm != 0) { /* if tgtm is 0 it remains 0 and tgtd remains negative */ /* get the target month's mdays */ unsigned int d2m = d2.m; unsigned int d2y = d2.y; if (--d2m < 1) { d2m = GREG_MONTHS_P_YEAR; d2y--; } tgtd += __get_mdays(d2y, d2m); tgtm--; #if !defined WITH_FAST_ARITH || defined OMIT_FIXUPS /* the non-fast arith has done the fixup already */ #else /* WITH_FAST_ARITH && !defined OMIT_FIXUPS */ } else if (tgtm == 0) { /* check if we're not diffing two lazy representations * e.g. 2010-02-28 and 2010-02-31 */ ; #endif /* !OMIT_FIXUPS */ } /* fill in the results */ res.ymd.y = tgtm / GREG_MONTHS_P_YEAR; res.ymd.m = tgtm % GREG_MONTHS_P_YEAR; res.ymd.d = tgtd; return res; } #endif /* ASPECT_DIFF */ #if defined ASPECT_STRF && !defined YMD_ASPECT_STRF_ #define YMD_ASPECT_STRF_ #endif /* ASPECT_STRF */ #undef ASPECT_YMD /* ymd.c ends here */ dateutils-0.4.5/lib/ywd.c000066400000000000000000000431371335042257000152440ustar00rootroot00000000000000/*** ywd.c -- guts for ywd dates * * Copyright (C) 2012-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of dateutils. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * **/ /* this is an attempt to code aspect-oriented */ #define ASPECT_YWD #include "nifty.h" #if !defined DEFUN # define DEFUN #endif /* !DEFUN */ /* table of 53-week years (years % 400) {4, 9, 15, 20, 26, 32, 37, 43, 48, 54, 60, 65, 71, 76, 82, 88, 93, 99, 105, 111, 116, 122, 128, 133, 139, 144, 150, 156, 161, 167, 172, 178, 184, 189, 195, 201, 207, 212, 218, 224, 229, 235, 240, 246, 252, 257, 263, 268, 274, 280, 285, 291, 296, 303, 308, 314, 320, 325, 331, 336, 342, 348, 353, 359, 364, 370, 376, 381, 387, 392, 398}; we could use gperf to get a perfect hash, thank god the list is fixed, but at the moment we let the compiler work it out */ #if defined GET_ISOWK_FULL_SWITCH #elif defined GET_ISOWK_28Y_SWITCH #else # define GET_ISOWK_FULL_SWITCH #endif #if !defined YWD_ASPECT_HELPERS_ #define YWD_ASPECT_HELPERS_ static dt_dow_t __ywd_get_jan01_wday(dt_ywd_t d) { /* hang of 0 means Mon, -1 Tue, -2 Wed, -3 Thu, 3 Fri, 2 Sat, 1 Sun */ int res; /* the second portion of the assert is trivially true */ assert(d.hang >= -3 /*&& d.hang <= 3*/); if (UNLIKELY((res = 1 - d.hang) <= 0)) { res += GREG_DAYS_P_WEEK; assert(res > DT_MIRACLEDAY); } return (dt_dow_t)res; } static int __ywd_get_jan01_hang(dt_dow_t j01) { /* Mon means hang of 0, Tue -1, Wed -2, Thu -3, Fri 3, Sat 2, Sun 1 */ int res; if (UNLIKELY((res = 1 - (int)j01) < -3)) { assert(res >= -6); return (int)GREG_DAYS_P_WEEK + res; } return res; } static __attribute__((unused)) dt_dow_t __ywd_get_dec31_wday(dt_ywd_t d) { /* a year starting on W ends on W if not a leap year */ dt_dow_t res = __ywd_get_jan01_wday(d); if (UNLIKELY(__leapp(d.y))) { if (++res > GREG_DAYS_P_WEEK) { /* wrap around DT_SUNDAY -> DT_MONDAY */ res = DT_MONDAY; } } return res; } #if defined GET_ISOWK_FULL_SWITCH DEFUN __attribute__((const, pure)) inline unsigned int __get_isowk(unsigned int y) { /* return the number of iso weeks in Y */ switch (y % 400) { default: break; case 4: case 9: case 15: case 20: case 26: case 32: case 37: case 43: case 48: case 54: case 60: case 65: case 71: case 76: case 82: case 88: case 93: case 99: case 105: case 111: case 116: case 122: case 128: case 133: case 139: case 144: case 150: case 156: case 161: case 167: case 172: case 178: case 184: case 189: case 195: case 201: case 207: case 212: case 218: case 224: case 229: case 235: case 240: case 246: case 252: case 257: case 263: case 268: case 274: case 280: case 285: case 291: case 296: case 303: case 308: case 314: case 320: case 325: case 331: case 336: case 342: case 348: case 353: case 359: case 364: case 370: case 376: case 381: case 387: case 392: case 398: return 53; } return 52; } static unsigned int __get_z31wk(unsigned int y) { /* return the week number of 31 dec in year Y, where weeks hanging over into * the new year are treated as 53 * In the 400 year cycle, there's 243 years with 53 weeks and * 157 years with 52 weeks. */ switch (y % 400U) { default: break; case 0: case 5: case 6: case 10: case 11: case 16: case 17: case 21: case 22: case 23: case 27: case 28: case 33: case 34: case 38: case 39: case 44: case 45: case 49: case 50: case 51: case 55: case 56: case 61: case 62: case 66: case 67: case 72: case 73: case 77: case 78: case 79: case 83: case 84: case 89: case 90: case 94: case 95: case 100: case 101: case 102: case 106: case 107: case 112: case 113: case 117: case 118: case 119: case 123: case 124: case 129: case 130: case 134: case 135: case 140: case 141: case 145: case 146: case 147: case 151: case 152: case 157: case 158: case 162: case 163: case 168: case 169: case 173: case 174: case 175: case 179: case 180: case 185: case 186: case 190: case 191: case 196: case 197: case 202: case 203: case 208: case 209: case 213: case 214: case 215: case 219: case 220: case 225: case 226: case 230: case 231: case 236: case 237: case 241: case 242: case 243: case 247: case 248: case 253: case 254: case 258: case 259: case 264: case 265: case 269: case 270: case 271: case 275: case 276: case 281: case 282: case 286: case 287: case 292: case 293: case 297: case 298: case 299: case 304: case 305: case 309: case 310: case 311: case 315: case 316: case 321: case 322: case 326: case 327: case 332: case 333: case 337: case 338: case 339: case 343: case 344: case 349: case 350: case 354: case 355: case 360: case 361: case 365: case 366: case 367: case 371: case 372: case 377: case 378: case 382: case 383: case 388: case 389: case 393: case 394: case 395: case 399: return 52; } /* more weeks with 53, so default to that */ return 53; } #elif defined GET_ISOWK_28Y_SWITCH DEFUN __attribute__((const, pure)) inline unsigned int __get_isowk(unsigned int y) { switch (y % 28U) { default: break; case 16: /* 1920, 1948, ... */ case 21: /* 1925, 1953, ... */ case 27: /* 1931, 1959, ... */ case 4: /* 1936, 1964, ... */ case 10: /* 1942, 1970, ... */ return 53; } return 52; } static unsigned int __get_z31wk(unsigned int y) { /* return the week number of 31 dec in year Y, where weeks hanging over into * the new year are treated as 53 * In the 400 year cycle, there's 243 years with 53 weeks and * 157 years with 52 weeks. */ switch (y % 28U) { default: break; /* pattern in the 28y cycle is: 5 1 4 1 5 1 4 1 1 4 1 */ case 0: case 5: case 6: case 10: case 11: case 16: case 17: case 21: case 22: case 23: case 27: return 52; } /* more weeks with 53, so default to that */ return 53; } #endif /* GET_ISOWK_* */ DEFUN __attribute__((pure)) dt_ywd_t __ywd_fixup(dt_ywd_t d) { /* given dates like 2012-W53-01 this returns 2013-W01-01 */ int nw; if (LIKELY(d.c <= 52)) { /* brill all years have 52 weeks */ ; } else if (UNLIKELY(d.c > (nw = __get_isowk(d.y)))) { d.c = nw; } return d; } #define canon_yc(y, c, hang) \ if (LIKELY(c >= 1 && c <= 52)) { \ /* all years support this */ \ ; \ } else if (UNLIKELY(c < 1)) { \ if (UNLIKELY(__leapp(--y))) { \ hang++; \ } \ if (++hang > 3) { \ hang -= GREG_DAYS_P_WEEK; \ } \ c += __get_isowk(y); \ } else if (UNLIKELY(c > __get_isowk(y))) { \ c -= __get_isowk(y); \ if (UNLIKELY(__leapp(y++))) { \ hang--; \ } \ if (--hang < -3) { \ hang += GREG_DAYS_P_WEEK; \ } \ } #endif /* !YWD_ASPECT_HELPERS_ */ #if defined ASPECT_GETTERS && !defined YWD_ASPECT_GETTERS_ #define YWD_ASPECT_GETTERS_ static dt_ywd_t __make_ywd_c(unsigned int y, unsigned int c, dt_dow_t w, unsigned int cc) { /* build a 8601 compliant ywd object from year Y, week C and weekday W * where C conforms to week-count convention cc */ dt_ywd_t res = {0}; dt_dow_t j01; int hang; /* this one's special as it needs the hang helper slot */ j01 = __get_jan01_wday(y); hang = __ywd_get_jan01_hang(j01); assert(w != DT_MIRACLEDAY); switch (cc) { default: case YWD_ISOWK_CNT: break; case YWD_ABSWK_CNT: if (hang == 1 && w < DT_SUNDAY) { /* n-th W in the year is n-th week, * year starts on sunday */ ; } else if (hang > 0 && w < DT_SUNDAY && w < j01) { /* n-th W in the year is n-th week, * in this case the year doesnt start on sunday */ ; } else if (hang <= 0 && (w >= j01 || w == DT_SUNDAY)) { /* n-th W in the year is n-th week */ ; } else if (hang > 0) { /* those weekdays that hang over into the last year */ c--; } else if (hang <= 0) { /* weekdays missing in the first week of Y */ c++; } canon_yc(y, c, hang); break; case YWD_SUNWK_CNT: if (j01 == DT_SUNDAY) { ; } else { c++; } break; case YWD_MONWK_CNT: if (j01 <= DT_MONDAY) { ; } else { c++; } break; } /* assign and fuck off */ res.y = y; res.c = c; res.w = w; res.hang = hang; return res; } static dt_ywd_t __make_ywd_yd_dow(unsigned int y, int yd, dt_dow_t dow) { /* build a 8601 compliant ywd object from year Y, day-of-year YD * and weekday DOW */ dt_ywd_t res = {0}; dt_dow_t j01; unsigned int c; int hang; /* deduce the weekday of the first, given the weekday * of the yd-th is DOW */ j01 = __get_jan01_yday_dow(yd, dow); hang = __ywd_get_jan01_hang(j01); /* compute weekday, decompose yd into 7p + q */ c = (yd + GREG_DAYS_P_WEEK - 1 - hang) / (signed int)GREG_DAYS_P_WEEK; /* fixup c (and y) */ canon_yc(y, c, hang); /* assign and fuck off */ res.y = y; res.c = c; res.w = dow; res.hang = hang; return res; } static dt_ywd_t __make_ywd_ybd(unsigned int y, int yd) { /* build a 8601 compliant ywd object from year Y and year-business-day YD */ dt_ywd_t res = {0}; dt_dow_t j01; unsigned int c; int w; int hang; /* this one's special as it needs the hang helper slot */ j01 = __get_jan01_wday(y); hang = __ywd_get_jan01_hang(j01); /* compute weekday, decompose yd into 7p + q */ c = (yd + DUWW_BDAYS_P_WEEK - 1) / (signed int)DUWW_BDAYS_P_WEEK; w = (yd + DUWW_BDAYS_P_WEEK - 1) % (signed int)DUWW_BDAYS_P_WEEK; if ((w += j01) > (signed int)DUWW_BDAYS_P_WEEK) { w -= DUWW_BDAYS_P_WEEK; c++; } else if (w < (signed int)DT_MONDAY) { w += DUWW_BDAYS_P_WEEK; c--; } /* fixup c (and y) */ canon_yc(y, c, hang); /* assign and fuck off */ res.y = y; res.c = c; res.w = w; res.hang = hang; return res; } static __attribute__((pure, const)) int __ywd_get_yday(dt_ywd_t d) { /* since everything is in ISO 8601 format, getting the doy is a matter of * counting how many days there are in a week. * This may return negative values and values larger than the number of * days in that year. */ return GREG_DAYS_P_WEEK * (d.c - 1) + d.w + d.hang; } static dt_dow_t __ywd_get_wday(dt_ywd_t that) { return (dt_dow_t)that.w; } static unsigned int __ywd_get_wcnt_mon(dt_ywd_t d) { /* given a YWD with week-count within the year (ISOWK_CNT convention) * return the week-count within the month (ABSWK_CNT convention) */ int yd = __ywd_get_yday(d); struct __md_s x = __yday_get_md(d.y, yd); return (x.d - 1) / 7 + 1; } static int __ywd_get_wcnt_year(dt_ywd_t d, unsigned int tgtcc) { dt_dow_t j01; if (tgtcc == YWD_ISOWK_CNT) { return d.c; } /* otherwise we need to shift things */ j01 = __ywd_get_jan01_wday(d); switch (tgtcc) { case YWD_ABSWK_CNT: if (d.w < j01) { return d.c - 1; } else if (d.hang < 0) { return d.c + 1; } break; case YWD_MONWK_CNT: if (j01 >= DT_TUESDAY && j01 < DT_SUNDAY) { return d.c - 1; } break; case YWD_SUNWK_CNT: if (j01 < DT_SUNDAY) { return d.c - 1; } break; default: break; } return d.c; } static struct __md_s __ywd_get_md(dt_ywd_t d) { int yday = __ywd_get_yday(d); struct __md_s res = __yday_get_md(d.y, yday); if (UNLIKELY(res.m == 0)) { res.m = 12; res.d--; } else if (UNLIKELY(res.m == 13)) { res.m = 1; } return res; } static unsigned int __ywd_get_mon(dt_ywd_t d) { int yd = __ywd_get_yday(d); return __yday_get_md(d.y, yd).m; } static unsigned int __ywd_get_year(dt_ywd_t d) { /* return the true gregorian year */ unsigned int y = d.y; if (d.c == 1) { dt_dow_t f01 = __ywd_get_jan01_wday(d); if (d.hang <= 0 && d.w < f01) { y--; } } else if (d.c >= __get_z31wk(y)) { dt_dow_t z31 = __ywd_get_dec31_wday(d); if (z31 < DT_SUNDAY && d.w > z31) { y++; } } return y; } #endif /* ASPECT_GETTERS */ #if defined ASPECT_CONV && !defined YWD_ASPECT_CONV_ #define YWD_ASPECT_CONV_ /* we need some of the stuff above, so get it */ #define ASPECT_GETTERS #include "ywd.c" #undef ASPECT_GETTERS static dt_ymd_t __ywd_to_ymd(dt_ywd_t d) { unsigned int y = __ywd_get_year(d); struct __md_s md = __ywd_get_md(d); #if defined HAVE_ANON_STRUCTS_INIT return (dt_ymd_t){.y = y, .m = md.m, .d = md.d}; #else /* !HAVE_ANON_STRUCTS_INIT */ { dt_ymd_t res; res.y = y; res.m = md.m; res.d = md.d; return res; } #endif /* HAVE_ANON_STRUCTS_INIT */ } static dt_ymcw_t __ywd_to_ymcw(dt_ywd_t d) { unsigned int y = __ywd_get_year(d); struct __md_s md = __ywd_get_md(d); unsigned int c; /* we obtain C from weekifying the month */ c = (md.d - 1U) / GREG_DAYS_P_WEEK + 1U; #if defined HAVE_ANON_STRUCTS_INIT return (dt_ymcw_t){.y = y, .m = md.m, .c = c, .w = d.w}; #else /* !HAVE_ANON_STRUCTS_INIT */ { dt_ymcw_t res; res.y = y; res.m = md.m; res.c = c; res.w = d.w; return res; } #endif /* HAVE_ANON_STRUCTS_INIT */ } static dt_daisy_t __ywd_to_daisy(dt_ywd_t d) { dt_daisy_t res; res = __jan00_daisy(d.y); res += __ywd_get_yday(d); return res; } static dt_yd_t __ywd_to_yd(dt_ywd_t d) { unsigned int y = __ywd_get_year(d); int x = __ywd_get_yday(d); if (UNLIKELY(x <= 0)) { /* gotta go for last years thing */ x += __get_ydays(d.y - 1); } else if (x > (int)__get_ydays(d.y)) { x -= __get_ydays(d.y); } #if defined HAVE_ANON_STRUCTS_INIT return (dt_yd_t){.y = y, .d = x}; #else /* !HAVE_ANON_STRUCTS_INIT */ dt_yd_t res; res.y = y; res.d = x; return res; #endif /* HAVE_ANON_STRUCTS_INIT */ } #endif /* ASPECT_CONV */ #if defined ASPECT_ADD && !defined YWD_ASPECT_ADD_ #define YWD_ASPECT_ADD_ static dt_ywd_t __ywd_fixup_w(unsigned int y, signed int w, dt_dow_t d, int hang) { dt_ywd_t res = {0}; /* fixup q */ if (LIKELY(w >= 1 && w <= 52)) { /* all years support this */ ; } else if (w < 1) { do { if (UNLIKELY(__leapp(--y))) { hang++; } if (++hang > 3) { hang -= GREG_DAYS_P_WEEK; } w += __get_isowk(y); } while (w < 1); } else { int nw; while (w > (nw = __get_isowk(y))) { w -= nw; if (UNLIKELY(__leapp(y++))) { hang--; } if (--hang < -3) { hang += GREG_DAYS_P_WEEK; } } } /* final assignment */ res.y = y; res.c = w; res.w = d; res.hang = hang; return res; } static dt_ywd_t __ywd_add_w(dt_ywd_t d, int n) { /* add N weeks to D */ signed int tgtc = d.c + n; return __ywd_fixup_w(d.y, tgtc, (dt_dow_t)d.w, d.hang); } static dt_ywd_t __ywd_add_d(dt_ywd_t d, int n) { /* add N days to D * we reduce this to __ywd_add_w() */ signed int aw = n / 7; signed int ad = n % 7; if ((ad += d.w) > (signed int)GREG_DAYS_P_WEEK) { ad -= GREG_DAYS_P_WEEK; aw++; } else if (ad <= 0) { ad += GREG_DAYS_P_WEEK; aw--; } d.w = (dt_dow_t)ad; return __ywd_add_w(d, aw); } static dt_ywd_t __ywd_add_b(dt_ywd_t d, int UNUSED(n)) { /* add N business days to D */ return d; } static dt_ywd_t __ywd_add_y(dt_ywd_t d, int n) { /* add N years to D */ dt_dow_t j01; d.y = d.y + n; /* recompute hang */ j01 = __get_jan01_wday(d.y); d.hang = __ywd_get_jan01_hang(j01); return d; } #endif /* ASPECT_ADD */ #if defined ASPECT_DIFF && !defined YWD_ASPECT_DIFF_ #define YWD_ASPECT_DIFF_ static struct dt_ddur_s __ywd_diff(dt_ywd_t d1, dt_ywd_t d2) { /* compute d2 - d1 entirely in terms of ymd but express the result as yd */ struct dt_ddur_s res = dt_make_ddur(DT_DURYWD, 0); signed int tgtd; signed int tgtw; signed int tgty; if (d1.u > d2.u) { /* swap d1 and d2 */ dt_ywd_t tmp = d1; res.neg = 1; d1 = d2; d2 = tmp; } /* first compute the difference in years */ tgty = (d2.y - d1.y); /* ... and weeks */ tgtw = (d2.c - d1.c); /* ... oh, and days, too */ tgtd = (d2.w ?: 7) - (d1.w ?: 7); /* add carry */ if (tgtd < 0) { tgtw--; tgtd += GREG_DAYS_P_WEEK; } if (tgtw < 0) { tgty--; tgtw += __get_isowk(d1.y + tgty); } /* fill in the results */ res.ywd.y = tgty; res.ywd.c = tgtw; res.ywd.w = tgtd; return res; } #endif /* ASPECT_DIFF */ #if defined ASPECT_STRF && !defined YWD_ASPECT_STRF_ #define YWD_ASPECT_STRF_ DEFUN void __prep_strfd_ywd(struct strpd_s *tgt, dt_ywd_t d) { /* place ywd data of THIS into D for printing with FMT. */ if (d.c == 1 && d.hang < 0 && d.w < __ywd_get_jan01_wday(d)) { /* put gregorian year into y and real year into q */ tgt->y = d.y - 1; tgt->q = d.y; } else if (d.c >= 53 && d.w >= __ywd_get_jan01_wday(d) + 1U/*coz 365 = 1 mod 7*/ + __leapp(d.y)) { /* put gregorian year into y and real year into q */ tgt->y = d.y + 1; tgt->q = d.y; } else { tgt->y = d.y; tgt->q = d.y; } /* business as usual here */ tgt->c = d.c; tgt->w = d.w; tgt->flags.real_y_in_q = 1; return; } #endif /* ASPECT_STRF */ /* ywd.c ends here */ dateutils-0.4.5/m4/000077500000000000000000000000001335042257000140375ustar00rootroot00000000000000dateutils-0.4.5/m4/ax_zoneinfo.m4000066400000000000000000000170101335042257000166170ustar00rootroot00000000000000# =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_zoneinfo.html # =========================================================================== # # SYNOPSIS # # AX_ZONEINFO([options...]) # # DESCRIPTION # # This macro finds compiled zoneinfo files. If successful it will define # HAVE_ZONEINFO per: # # AC_DEFINE([HAVE_ZONEINFO], [1], [...]) # # and have the variable TZDIR point to the zoneinfo directory as per # # AC_SUBST([TZDIR]) # AC_DEFINE_UNQUOTED([TZDIR], [/path/to/zic/files], [...]) # # Optionally, OPTIONS can be `right' to trigger further tests that will # determine if leap second fix-ups are available. If so the variables # HAVE_ZONEINFO_RIGHT, ZONEINFO_UTC_RIGHT and TZDIR_RIGHT will be populated: # # AC_DEFINE([HAVE_ZONEINFO_RIGHT], [1], [...]) # AC_SUBST([TZDIR_RIGHT]) # AC_DEFINE_UNQUOTED([TZDIR_RIGHT], [/path/to/right/zic/files], [...]) # AC_SUBST([ZONEINFO_UTC_RIGHT]) # AC_DEFINE_UNQUOTED([ZONEINFO_UTC_RIGHT], [$ZONEINFO_UTC_RIGHT], [...]) # # # LICENSE # # Copyright (c) 2012 Sebastian Freundt # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. #serial 1 AC_DEFUN([AX_ZONEINFO_TZFILE_H], [dnl dnl not totally necessary (yet), as we can simply inspect the tzfiles dnl ourselves, but it certainly helps AC_CHECK_HEADER([tzfile.h]) ])dnl AX_ZONEINFO_TZFILE_H AC_DEFUN([AX_ZONEINFO_CHECK_TZFILE], [dnl dnl AX_ZONEINFO_CHECK_TZFILE([FILE], [ACTION-IF-VALID], [ACTION-IF-NOT]) dnl secret switch is the 4th argument, which determines the ret code dnl of the leapcnt check pushdef([probe], [$1]) pushdef([if_found], [$2]) pushdef([if_not_found], [$3]) AC_REQUIRE([AX_ZONEINFO_TZFILE_H]) if test -z "${ax_tmp_zoneinfo_nested}"; then AC_MSG_CHECKING([zoneinfo file ]probe[]) fi AC_LANG_PUSH([C]) AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include #include #include #include ]]ifelse([$4], [], [], [[ #define CHECK_LEAPCNT ]]$4[[ ]])[[ /* simplified struct */ struct tzhead { char tzh_magic[4]; /* TZ_MAGIC */ char tzh_version[1]; /* '\0' or '2' as of 2005 */ char tzh_reserved[15]; /* reserved--must be zero */ char tzh_ttisgmtcnt[4]; /* coded number of trans. time flags */ char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */ char tzh_leapcnt[4]; /* coded number of leap seconds */ char tzh_timecnt[4]; /* coded number of transition times */ char tzh_typecnt[4]; /* coded number of local time types */ char tzh_charcnt[4]; /* coded number of abbr. chars */ }; int main(int argc, char *argv[]) { struct tzhead foo; int f; if (argc <= 1) { return 0; } else if ((f = open(argv[1], O_RDONLY, 0644)) < 0) { return 1; } else if (read(f, &foo, sizeof(foo)) != sizeof(foo)) { return 1; } else if (close(f) < 0) { return 1; } /* inspect the header */ if (memcmp(foo.tzh_magic, "TZif", sizeof(foo.tzh_magic))) { return 1; } else if (*foo.tzh_version && *foo.tzh_version != '2') { return 1; #if defined CHECK_LEAPCNT } else if (!foo.tzh_leapcnt[0] && !foo.tzh_leapcnt[1] && !foo.tzh_leapcnt[2] && !foo.tzh_leapcnt[3]) { return CHECK_LEAPCNT; #endif /* CHECK_LEAPCNT */ } /* otherwise everything's in order */ return 0; } ]])], [## call the whole shebang again with the tzfile if ./conftest$EXEEXT probe; then if test -z "${ax_tmp_zoneinfo_nested}"; then AC_MSG_RESULT([looking good]) fi []if_found[] else if test -z "${ax_tmp_zoneinfo_nested}"; then AC_MSG_RESULT([looking bad ${ax_tmp_rc}]) fi []if_not_found[] fi ], [ if test -z "${ax_tmp_zoneinfo_nested}"; then AC_MSG_RESULT([impossible]) fi []if_not_found[]]) AC_LANG_POP([C]) popdef([probe]) popdef([if_found]) popdef([if_not_found]) ])dnl AX_ZONEINFO_CHECK_TZFILE AC_DEFUN([AX_ZONEINFO_TZDIR], [dnl dnl we consider a zoneinfo directory properly populated when it dnl provides UTC or UCT or Universal or Zulu pushdef([check_tzdir], [dnl pushdef([dir], $]1[)dnl test -n []dir[] && test -d []dir[] dnl popdef([dir])dnl ])dnl check_tzdir dnl try /etc/localtime first, sometimes it's a link into TZDIR if test -L "/etc/localtime"; then TZDIR_cand="`readlink /etc/localtime` ${TZDIR_cand}" fi dnl oh, how about we try and check if there is a TZDIR already if check_tzdir(["${TZDIR}"]); then ## bingo TZDIR_cand="${TZDIR} ${TZDIR_cand}" fi dnl often there's a tzselect util which contains the TZDIR path AC_PATH_PROG([TZSELECT], [tzselect]) if test -n "${ac_cv_path_TZSELECT}"; then dnl snarf the value valtmp="`mktemp`" strings "${ac_cv_path_TZSELECT}" | \ grep -F 'TZDIR=' > "${valtmp}" . "${valtmp}" TZDIR_cand="${TZDIR} ${TZDIR_cand}" rm -f -- "${valtmp}" fi dnl lastly, append the usual suspects TZDIR_cand="${TZDIR_cand} \ /usr/share/zoneinfo \ /usr/lib/zoneinfo \ /usr/local/etc/zoneinfo \ /usr/share/lib/zoneinfo \ " dnl go through our candidates AC_CACHE_CHECK([for TZDIR], [ax_cv_zoneinfo_tzdir], [dnl ax_tmp_zoneinfo_nested="yes" for c in ${TZDIR_cand}; do ax_cv_zoneinfo_utc="" for f in "UTC" "UCT" "Universal" "Zulu"; do AX_ZONEINFO_CHECK_TZFILE(["${c}/${f}"], [ dnl ACTION-IF-FOUND ax_cv_zoneinfo_utc="${c}/${f}" break ]) done if test -n "${ax_cv_zoneinfo_utc}"; then ax_cv_zoneinfo_tzdir="${c}" break fi done ax_tmp_zoneinfo_nested="" ])dnl ax_cv_tzdir TZDIR="${ax_cv_zoneinfo_tzdir}" AC_SUBST([TZDIR]) if check_tzdir(["${ax_cv_zoneinfo_tzdir}"]); then AC_DEFINE([HAVE_ZONEINFO], [1], [dnl Define when zoneinfo directory has been present during configuration.]) AC_DEFINE_UNQUOTED([TZDIR], ["${ax_cv_zoneinfo_tzdir}"], [ Configuration time zoneinfo directory.]) fi if test -n "${ax_cv_zoneinfo_utc}"; then AC_DEFINE_UNQUOTED([ZONEINFO_UTC], ["${ax_cv_zoneinfo_utc}"], [ Leap-second UNAWARE UTC zoneinfo file.]) fi popdef([check_tzdir]) ])dnl AX_ZONEINFO_TZDIR AC_DEFUN([AX_ZONEINFO_RIGHT], [dnl AC_REQUIRE([AX_ZONEINFO_TZDIR]) TZDIR_cand="${TZDIR} \ ${TZDIR}/leapseconds \ ${TZDIR}-leaps \ ${TZDIR}/right \ ${TZDIR}-posix \ ${TZDIR}/posix \ " dnl go through our candidates AC_CACHE_CHECK([for leap second file], [ax_cv_zoneinfo_utc_right], [dnl ax_tmp_zoneinfo_nested="yes" if test -n "${ax_cv_zoneinfo_utc}"; then __utc_file="`basename "${ax_cv_zoneinfo_utc}"`" for c in ${TZDIR_cand}; do if test -d "${c}"; then c="${c}/${__utc_file}" fi AX_ZONEINFO_CHECK_TZFILE(["${c}"], [ dnl ACTION-IF-FOUND ax_cv_zoneinfo_utc_right="${c}" break ], [:], [2]) done fi ax_tmp_zoneinfo_nested="" ])dnl ax_cv_tzdir ZONEINFO_UTC_RIGHT="${ax_cv_zoneinfo_utc_right}" AC_SUBST([ZONEINFO_UTC_RIGHT]) AC_SUBST([TZDIR_RIGHT]) if test -n "${ax_cv_zoneinfo_utc_right}"; then TZDIR_RIGHT="`dirname ${ax_cv_zoneinfo_utc_right}`" AC_DEFINE([HAVE_ZONEINFO_RIGHT], [1], [dnl Define when zoneinfo directory has been present during configuration.]) AC_DEFINE_UNQUOTED([TZDIR_RIGHT], ["${TZDIR_RIGHT}"], [ Configuration time zoneinfo directory.]) AC_DEFINE_UNQUOTED([ZONEINFO_UTC_RIGHT], ["${ax_cv_zoneinfo_utc_right}"], [ Leap-second aware UTC zoneinfo file.]) fi ])dnl AX_ZONEINFO_RIGHT AC_DEFUN([AX_ZONEINFO], [ AC_REQUIRE([AX_ZONEINFO_TZDIR]) ifelse([$1], [right], [ AC_REQUIRE([AX_ZONEINFO_RIGHT]) ]) AC_ARG_VAR([TZDIR], [Directory with compiled zoneinfo files.]) ])dnl AX_ZONEINFO dnl ax_zoneinfo.m4 ends here dateutils-0.4.5/m4/clitosis.m4000066400000000000000000000037111335042257000161340ustar00rootroot00000000000000dnl clitosis.m4 --- checks necessary for the clitosis test harness dnl dnl Copyright (C) 2013-2016 Sebastian Freundt dnl dnl Author: Sebastian Freundt dnl dnl Redistribution and use in source and binary forms, with or without dnl modification, are permitted provided that the following conditions dnl are met: dnl dnl 1. Redistributions of source code must retain the above copyright dnl notice, this list of conditions and the following disclaimer. dnl dnl 2. Redistributions in binary form must reproduce the above copyright dnl notice, this list of conditions and the following disclaimer in the dnl documentation and/or other materials provided with the distribution. dnl dnl 3. Neither the name of the author nor the names of any contributors dnl may be used to endorse or promote products derived from this dnl software without specific prior written permission. dnl dnl THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR dnl IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED dnl WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE dnl DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE dnl FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR dnl CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF dnl SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR dnl BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, dnl WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE dnl OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN dnl IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. dnl dnl This file is part of clitosis. AC_DEFUN([AX_CHECK_CLITOSIS], [dnl ## check for pseudo-tty support AC_CHECK_HEADERS([pty.h]) AM_CONDITIONAL([HAVE_PTY_H], [test "${ac_cv_header_pty_h}" = "yes"]) ## we might want to use splice(2) AC_CHECK_FUNCS([splice]) ])dnl AX_CHECK_CLITOSIS dnl clitosis.m4 ends here dateutils-0.4.5/m4/sxe-compiler.m4000066400000000000000000000555051335042257000167220ustar00rootroot00000000000000dnl compiler.m4 --- compiler magic dnl dnl Copyright (C) 2005-2016 Sebastian Freundt dnl Copyright (c) 2005 Steven G. Johnson dnl Copyright (c) 2005 Matteo Frigo dnl dnl Author: Sebastian Freundt dnl dnl Redistribution and use in source and binary forms, with or without dnl modification, are permitted provided that the following conditions dnl are met: dnl dnl 1. Redistributions of source code must retain the above copyright dnl notice, this list of conditions and the following disclaimer. dnl dnl 2. Redistributions in binary form must reproduce the above copyright dnl notice, this list of conditions and the following disclaimer in the dnl documentation and/or other materials provided with the distribution. dnl dnl 3. Neither the name of the author nor the names of any contributors dnl may be used to endorse or promote products derived from this dnl software without specific prior written permission. dnl dnl THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR dnl IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED dnl WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE dnl DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE dnl FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR dnl CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF dnl SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR dnl BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, dnl WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE dnl OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN dnl IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. dnl dnl This file is part of SXEmacs. ##### http://autoconf-archive.cryp.to/ax_check_compiler_flags.html ## renamed the prefix to SXE_ AC_DEFUN([SXE_CHECK_COMPILER_FLAG], [dnl dnl SXE_CHECK_COMPILER_FLAG([flag], [action-if-accepted], [action-if-not-accepted]) AC_MSG_CHECKING([whether _AC_LANG compiler accepts $1]) ## store werror status, then turn -Werror on save_ac_[]_AC_LANG_ABBREV[]_werror_flag="${ac_[]_AC_LANG_ABBREV[]_werror_flag}" AC_LANG_WERROR AC_CACHE_VAL(AS_TR_SH(sxe_cv_[]_AC_LANG_ABBREV[]_flag_$1), [dnl sxe_save_FLAGS="${[]_AC_LANG_PREFIX[]FLAGS}" _AC_LANG_PREFIX[]FLAGS="$1" AC_COMPILE_IFELSE([AC_LANG_PROGRAM($4)], eval AS_TR_SH(sxe_cv_[]_AC_LANG_ABBREV[]_flag_$1)="yes", eval AS_TR_SH(sxe_cv_[]_AC_LANG_ABBREV[]_flag_$1)="no") _AC_LANG_PREFIX[]FLAGS="${sxe_save_FLAGS}" ]) eval sxe_check_flag=$AS_TR_SH(sxe_cv_[]_AC_LANG_ABBREV[]_flag_$1) ac_[]_AC_LANG_ABBREV[]_werror_flag="${save_ac_[]_AC_LANG_ABBREV[]_werror_flag}" AC_MSG_RESULT([${sxe_check_flag}]) if test "${sxe_check_flag}" = "yes"; then : $2 else : $3 fi ])dnl SXE_CHECK_COMPILER_FLAG AC_DEFUN([SXE_CHECK_PREPROC_FLAG], [dnl dnl SXE_CHECK_CPP_FLAG([flag], [action-if-found], [action-if-not-found]) AC_MSG_CHECKING([whether _AC_LANG preprocessor accepts $1]) ## store werror status, then turn -Werror on save_ac_[]_AC_LANG_ABBREV[]_werror_flag="${ac_[]_AC_LANG_ABBREV[]_werror_flag}" AC_LANG_WERROR AC_CACHE_VAL(AS_TR_SH(sxe_cv_[]_AC_LANG_ABBREV[]pp_flag_$1), [dnl sxe_save_FLAGS="${[]_AC_LANG_PREFIX[]PPFLAGS}" _AC_LANG_PREFIX[]PPFLAGS="$1" AC_PREPROC_IFELSE([AC_LANG_PROGRAM()], eval AS_TR_SH(sxe_cv_[]_AC_LANG_ABBREV[]pp_flag_$1)="yes", eval AS_TR_SH(sxe_cv_[]_AC_LANG_ABBREV[]pp_flag_$1)="no") _AC_LANG_PREFIX[]PPFLAGS=$sxe_save_FLAGS ]) eval sxe_check_flag=$AS_TR_SH(sxe_cv_[]_AC_LANG_ABBREV[]pp_flag_$1) ac_[]_AC_LANG_ABBREV[]_werror_flag="${save_ac_[]_AC_LANG_ABBREV[]_werror_flag}" AC_MSG_RESULT([${sxe_check_flag}]) if test "${sxe_check_flag}" = "yes"; then : $2 else : $3 fi ])dnl SXE_CHECK_PREPROC_FLAG AC_DEFUN([SXE_CHECK_CCLD_FLAG], [dnl dnl SXE_CHECK_CCLD_FLAG([flag], [action-if-accepted], [action-if-not-accepted]) AC_MSG_CHECKING([whether _AC_LANG linker accepts $1]) ## store werror status, then turn -Werror on save_ac_[]_AC_LANG_ABBREV[]_werror_flag="${ac_[]_AC_LANG_ABBREV[]_werror_flag}" AC_LANG_WERROR AC_CACHE_VAL(AS_TR_SH(sxe_cv_[]_AC_LANG_ABBREV[]_flag_$1), [dnl sxe_save_FLAGS="${[]_AC_LANG_PREFIX[]FLAGS}" _AC_LANG_PREFIX[]FLAGS="$1" AC_LINK_IFELSE([AC_LANG_PROGRAM()], eval AS_TR_SH(sxe_cv_[]_AC_LANG_ABBREV[]_flag_$1)="yes", eval AS_TR_SH(sxe_cv_[]_AC_LANG_ABBREV[]_flag_$1)="no") _AC_LANG_PREFIX[]FLAGS="${sxe_save_FLAGS}" ]) eval sxe_check_flag=$AS_TR_SH(sxe_cv_[]_AC_LANG_ABBREV[]_flag_$1) ac_[]_AC_LANG_ABBREV[]_werror_flag="${save_ac_[]_AC_LANG_ABBREV[]_werror_flag}" AC_MSG_RESULT([${sxe_check_flag}]) if test "${sxe_check_flag}" = "yes"; then : $2 else : $3 fi ])dnl SXE_CHECK_CCLD_FLAG AC_DEFUN([SXE_DEBUGFLAGS], [dnl ## distinguish between different compilers, no? SXE_CHECK_COMPILER_FLAG([-g]) SXE_CHECK_COMPILER_FLAG([-g3]) AC_PATH_PROG([DBX], [dbx]) if test -n "$ac_cv_path_DBX"; then SXE_CHECK_COMPILER_FLAG([-gstabs]) SXE_CHECK_COMPILER_FLAG([-gstabs3]) SXE_CHECK_COMPILER_FLAG([-gxcoff]) SXE_CHECK_COMPILER_FLAG([-gxcoff3]) fi AC_PATH_PROG([GDB], [gdb]) if test -n "$ac_cv_path_GDB"; then SXE_CHECK_COMPILER_FLAG([-ggdb]) SXE_CHECK_COMPILER_FLAG([-ggdb3]) fi AC_PATH_PROG([SDB], [sdb]) if test -n "$ac_cv_path_SDB"; then SXE_CHECK_COMPILER_FLAG([-gcoff]) SXE_CHECK_COMPILER_FLAG([-gcoff3]) fi ## final evaluation debugflags="" ## gdb if test "$sxe_cv_c_flag__ggdb3" = "yes"; then debugflags="$debugflags -ggdb3" elif test "$sxe_cv_c_flag__ggdb" = "yes"; then debugflags="$debugflags -ggdb" fi ## stabs if test "$sxe_cv_c_flag__gstabs3" = "yes"; then debugflags="$debugflags -gstabs3" elif test "$sxe_cv_c_flag__gstabs" = "yes"; then debugflags="$debugflags -gstabs" fi ## coff if test "$sxe_cv_c_flag__gcoff3" = "yes"; then debugflags="$debugflags -gcoff3" elif test "$sxe_cv_c_flag__gcoff" = "yes"; then debugflags="$debugflags -gcoff" fi ## xcoff if test "$sxe_cv_c_flag__gxcoff3" = "yes"; then debugflags="$debugflags -gxcoff3" elif test "$sxe_cv_c_flag__gxcoff" = "yes"; then debugflags="$debugflags -gxcoff" fi if test -z "debugflags" -a \ "$sxe_cv_c_flag__g" = "yes"; then debugflags="$debugflags -g" fi SXE_CHECK_COMPILER_FLAG([-ftime-report]) SXE_CHECK_COMPILER_FLAG([-fmem-report]) SXE_CHECK_COMPILER_FLAG([-fvar-tracking]) SXE_CHECK_COMPILER_FLAG([-save-temps]) #if test "$sxe_cv_c_flag__ggdb3" = "yes" -a \ # "$sxe_cv_c_flag__fvar_tracking" = "yes"; then # debugflags="$debugflags -fvar-tracking" #fi AC_MSG_CHECKING([for preferred debugging flags]) AC_MSG_RESULT([${debugflags}]) ])dnl SXE_DEBUGFLAGS AC_DEFUN([SXE_WARNFLAGS], [dnl ## Calculate warning flags. We separate the flags for warnings from ## the other flags because we want to force the warnings to be seen ## by everyone who doesn't specifically override them. ## by default we want the -Wall level SXE_CHECK_COMPILER_FLAG([-Wall], [warnflags="-Wall"]) SXE_CHECK_COMPILER_FLAG([-qinfo], [ warnflags="${warnflags} -qinfo"]) SXE_CHECK_COMPILER_FLAG([-Wextra], [ warnflags="${warnflags} -Wextra"]) ## Yuck, bad compares have been worth at ## least 3 crashes! ## Warnings about char subscripts are pretty ## pointless, though, ## and we use them in various places. SXE_CHECK_COMPILER_FLAG([-Wsign-compare], [ warnflags="$warnflags -Wsign-compare"]) SXE_CHECK_COMPILER_FLAG([-Wno-char-subscripts], [ warnflags="$warnflags -Wno-char-subscripts"]) SXE_CHECK_COMPILER_FLAG([-Wundef], [ warnflags="$warnflags -Wundef"]) ## too much at the moment, we rarely define protos #warnflags="$warnflags -Wmissing-prototypes -Wstrict-prototypes" ## somehow clang seems to think -Wpacked is to inform me ## about how unnecessary the packed attr is, so conditionalise ... SXE_CHECK_COMPILER_FLAG([-Wpacked], [ warnflags="$warnflags -Wpacked"], [:], [[ #if defined __clang__ # error #endif /* __clang__ */ ]]) ## glibc is intentionally not `-Wpointer-arith'-clean. ## Ulrich Drepper has rejected patches to fix ## the glibc header files. ## we dont care SXE_CHECK_COMPILER_FLAG([-Wpointer-arith], [ warnflags="$warnflags -Wpointer-arith"]) SXE_CHECK_COMPILER_FLAG([-Wshadow], [ warnflags="$warnflags -Wshadow"]) ## our code lacks declarations almost all the time SXE_CHECK_COMPILER_FLAG([-Wmissing-declarations], [ warnflags="$warnflags -Wmissing-declarations"]) SXE_CHECK_COMPILER_FLAG([-Wmissing-prototypes], [ warnflags="$warnflags -Wmissing-prototypes"]) ## gcc can't practically inline anything, so exclude this case "${CC}" in dnl ( *"gcc"*) ;; dnl ( *) SXE_CHECK_COMPILER_FLAG([-Winline], [ warnflags="$warnflags -Winline"]) ;; esac SXE_CHECK_COMPILER_FLAG([-Wbad-function-cast], [ warnflags="$warnflags -Wbad-function-cast"]) SXE_CHECK_COMPILER_FLAG([-Wcast-qual], [ warnflags="$warnflags -Wcast-qual"]) SXE_CHECK_COMPILER_FLAG([-Wcast-align], [ warnflags="$warnflags -Wcast-align"]) ## warn about incomplete switches ## for gcc, see http://gcc.gnu.org/bugzilla/show_bug.cgi?id=50422 ## we used to have -Wswitch-default and -Wswitch-enum but that ## set gcc off quite badly in the nested switch case SXE_CHECK_COMPILER_FLAG([-Wno-switch], [ warnflags="$warnflags -Wno-switch"]) SXE_CHECK_COMPILER_FLAG([-Wunused-function], [ warnflags="$warnflags -Wunused-function"]) SXE_CHECK_COMPILER_FLAG([-Wunused-variable], [ warnflags="$warnflags -Wunused-variable"]) SXE_CHECK_COMPILER_FLAG([-Wunused-parameter], [ warnflags="$warnflags -Wunused-parameter"]) SXE_CHECK_COMPILER_FLAG([-Wunused-value], [ warnflags="$warnflags -Wunused-value"]) SXE_CHECK_COMPILER_FLAG([-Wunused], [ warnflags="$warnflags -Wunused"]) SXE_CHECK_COMPILER_FLAG([-Wmaybe-uninitialized], [ warnflags="${warnflags} -Wmaybe-uninitialized"]) SXE_CHECK_COMPILER_FLAG([-Wnopragma], [ warnflags="$warnflags -Wnopragma"]) SXE_CHECK_COMPILER_FLAG([-fdiagnostics-show-option], [ warnflags="${warnflags} -fdiagnostics-show-option"]) SXE_CHECK_COMPILER_FLAG([-Wunknown-pragmas], [ warnflags="$warnflags -Wunknown-pragmas"]) SXE_CHECK_COMPILER_FLAG([-Wuninitialized], [ warnflags="$warnflags -Wuninitialized"]) SXE_CHECK_COMPILER_FLAG([-Wreorder], [ warnflags="$warnflags -Wreorder"]) SXE_CHECK_COMPILER_FLAG([-Wdeprecated], [ warnflags="$warnflags -Wdeprecated"]) SXE_CHECK_COMPILER_FLAG([-Wno-parentheses], [ warnflags="${warnflags} -Wno-parentheses"]) ## icc specific SXE_CHECK_COMPILER_FLAG([-Wcheck], [ warnflags="$warnflags -Wcheck"]) dnl SXE_CHECK_COMPILER_FLAG([-Wp64], [ dnl warnflags="$warnflags -Wp64"]) SXE_CHECK_COMPILER_FLAG([-Wstrict-aliasing], [ warnflags="$warnflags -Wstrict-aliasing"]) SXE_CHECK_COMPILER_FLAG([-w3], [ warnflags="$warnflags -w3"]) SXE_CHECK_COMPILER_FLAG([-diag-disable 10237], [dnl warnflags="${warnflags} -diag-disable 10237"], [ SXE_CHECK_COMPILER_FLAG([-wd 10237], [dnl warnflags="${warnflags} -wd 10237"])]) SXE_CHECK_COMPILER_FLAG([-diag-disable 2102], [dnl warnflags="${warnflags} -diag-disable 2102"], [ SXE_CHECK_COMPILER_FLAG([-wd 2102], [dnl warnflags="${warnflags} -wd 2102"])]) SXE_CHECK_COMPILER_FLAG([-debug inline-debug-info], [ warnflags="${warnflags} -debug inline-debug-info"]) SXE_CHECK_COMPILER_FLAG([-diag-enable remark,vec,par], [ warnflags="${warnflags} -diag-enable remark,vec,par"]) ## for dfp754 SXE_CHECK_COMPILER_FLAG([-Wunsuffixed-float-constants], [ warnflags="$warnflags -Wunsuffixed-float-constants"]) AC_MSG_CHECKING([for preferred warning flags]) AC_MSG_RESULT([${warnflags}]) ])dnl SXE_WARNFLAGS AC_DEFUN([SXE_OPTIFLAGS], [dnl AC_REQUIRE([SXE_USER_CFLAGS]) AC_REQUIRE([SXE_WARNFLAGS]) case " ${CFLAGS} ${EXTRA_CFLAGS} " in (*" -O"[[0-9]]" "*) ;; (*" -Os "*) ;; (*" -Og "*) ;; (*" -Ofast "*) ;; (*" -O "*) ;; (*) SXE_CHECK_COMPILER_FLAG([-O3], [ optiflags="${optiflags} -O3"]) ;; esac SXE_CHECK_COMPILER_FLAG([-ipo], [ optiflags="${optiflags} -ipo" AC_CHECK_TOOLS([AR], [xiar ar], [false]) AC_CHECK_TOOLS([LD], [xild ld], [false]) ## fiddle with xiar and xild params, kick ansi aliasing warnings if test "${ac_cv_prog_ac_ct_AR}" = "xiar"; then AR="${AR} -qdiag-disable=2102" fi if test "${ac_cv_prog_ac_ct_LD}" = "xild"; then LD="${LD} -qdiag-disable=2102" fi ]) SXE_CHECK_COMPILER_FLAG([-no-prec-div], [ optiflags="${optiflags} -no-prec-div"]) ])dnl SXE_OPTIFLAGS AC_DEFUN([SXE_CC_NATIVE], [dnl dnl Usage: SXE_CC_NATIVE([yes|no]) AC_ARG_ENABLE([native], [dnl AS_HELP_STRING(m4_case([$1], [yes], [--disable-native], [--enable-native]), [ Use code native to the build machine.])], [enable_native="${enableval}"], [enable_native="$1"]) ## -fast implies -static which is a dream but ## packager prefer dynamic binaries dnl SXE_CHECK_COMPILER_FLAG([-fast], [ dnl optiflags="${optiflags} -fast"]) ## auto-vectorisation dnl SXE_CHECK_COMPILER_FLAG([-axMIC-AVX512,CORE-AVX2,CORE-AVX-I,AVX,SSSE3], [ dnl optiflags="${optiflags} -axMIC-AVX512,CORE-AVX2,CORE-AVX-I,AVX,SSSE3"]) if test "${enable_native}" = "yes"; then case " ${CFLAGS} ${EXTRA_CFLAGS}" in (*" -mtune"*) ## don't tune ;; (*" -march"*) ## don't set march ;; (*" -m32 "*) ## don't bother ;; (*" -m64 "*) ## don't bother ;; (*) SXE_CHECK_COMPILER_FLAG([-xHost], [ optiflags="${optiflags} -xHost"], [ ## non-icc SXE_CHECK_COMPILER_FLAG([-mtune=native -march=native], [ optiflags="${optiflags} -mtune=native -march=native"]) ]) ;; esac fi ])dnl SXE_CC_NATIVE AC_DEFUN([SXE_FEATFLAGS], [dnl ## default flags for needed features AC_REQUIRE([SXE_CHECK_COMPILER_XFLAG]) XCCFLAG="${XFLAG}" ## recent gentoos went ballistic again, they compile PIE gcc's ## but there's no way to turn that misconduct off ... ## however I've got one report about a working PIE build ## we'll just check for -nopie here, if it works, we turn it on ## (and hence PIE off) and hope bug 16 remains fixed SXE_CHECK_COMPILER_FLAG([-nopie], [featflags="$featflags -nopie"]) ## icc and gcc related ## check if some stuff can be staticalised ## actually requires SXE_WARNFLAGS so warnings would be disabled ## that affect the outcome of the following tests SXE_CHECK_COMPILER_FLAG([-static-intel], [ featflags="${featflags} -static-intel" XCCLDFLAGS="${XCCLDFLAGS} \${XCCFLAG} -static-intel"], [:]) SXE_CHECK_COMPILER_FLAG([-static-libgcc], [ featflags="${featflags} -static-libgcc" XCCLDFLAGS="${XCCLDFLAGS} \${XCCFLAG} -static-libgcc"], [:]) SXE_CHECK_COMPILER_FLAG([-intel-extensions], [dnl featflags="${featflags} -intel-extensions"]) ## check if ipo needs passing to the linker if test "${sxe_cv_c_flag__ipo}" = "yes"; then XCCLDFLAGS="${XCCLDFLAGS} \${XCCFLAG} -ipo" fi ## also pass on some diags to the linker if test "${sxe_cv_c_flag__diag_disable_10237}" = "yes"; then XCCLDFLAGS="${XCCLDFLAGS} \${XCCFLAG} -diag-disable=10237" fi if test "${sxe_cv_c_flag__diag_disable_2102}" = "yes"; then XCCLDFLAGS="${XCCLDFLAGS} \${XCCFLAG} -diag-disable=2102" fi AC_SUBST([XCCLDFLAGS]) AC_SUBST([XCCFLAG]) ])dnl SXE_FEATFLAGS AC_DEFUN([SXE_CHECK_COMPILER_XFLAG], [dnl if test "${XFLAG}" = ""; then SXE_CHECK_CCLD_FLAG([-XCClinker -foo], [XFLAG="-XCClinker"]) fi if test "${XFLAG}" = ""; then SXE_CHECK_CCLD_FLAG([-Xlinker -foo], [XFLAG="-Xlinker"]) fi AC_SUBST([XFLAG]) ])dnl SXE_CHECK_COMPILER_XFLAG AC_DEFUN([SXE_USER_CFLAGS], [dnl AC_MSG_CHECKING([for user provided CFLAGS/EXTRA_CFLAGS]) CFLAGS="${ac_cv_env_CFLAGS_value}" AC_MSG_RESULT([${CFLAGS} ${EXTRA_CFLAGS}]) ])dnl SXE_USER_CFLAGS AC_DEFUN([SXE_CHECK_CFLAGS], [dnl dnl Usage: SXE_CHECK_CFLAGS([option ...]) dnl valid options include: dnl + native[=yes|no] Emit the --enable-native flag ## those are passed on to our determined CFLAGS AC_ARG_VAR([EXTRA_CFLAGS], [C compiler flags to be APPENDED.]) ## check for user provided flags AC_REQUIRE([SXE_USER_CFLAGS]) ## Use either command line flag, environment var, or autodetection SXE_DEBUGFLAGS SXE_WARNFLAGS SXE_OPTIFLAGS m4_foreach_w([opt], [$1], [dnl m4_case(opt, [native], [SXE_CC_NATIVE], [native=yes], [SXE_CC_NATIVE([yes])], [native=no], [SXE_CC_NATIVE([no])]) ]) SXE_CFLAGS="${SXE_CFLAGS} ${debugflags} ${optiflags} ${warnflags}" SXE_FEATFLAGS SXE_CFLAGS="${SXE_CFLAGS} ${featflags}" save_ac_c_werror_flag="${ac_c_werror_flag}" CFLAGS="${CFLAGS} ${SXE_CFLAGS} ${EXTRA_CFLAGS}" AC_MSG_CHECKING([for preferred CFLAGS]) AC_MSG_RESULT([${CFLAGS}]) AC_MSG_NOTICE([ If you wish to APPEND your own flags you want to stop here and rerun the configure script like so: configure EXTRA_CFLAGS= If you wish to OVERRIDE these flags you want to stop here too and rerun the configure script like this: configure CFLAGS= You can always override the determined CFLAGS, partially or totally, using make -C CFLAGS= [target] or make CFLAGS= [target] respectively ]) ac_c_werror_flag="${save_ac_c_werror_flag}" ])dnl SXE_CHECK_CFLAGS AC_DEFUN([SXE_CHECK_CC], [dnl dnl SXE_CHECK_CC([STANDARDS]) dnl standards are flavours supported by the compiler chosen with AC_PROG_CC pushdef([stds], m4_default([$1], [gnu11 c11 gnu99 c99])) AC_REQUIRE([AC_CANONICAL_HOST]) AC_REQUIRE([AC_CANONICAL_BUILD]) AC_REQUIRE([AC_PROG_CPP]) AC_REQUIRE([AC_PROG_CC]) AC_HEADER_STDC case "${CC}" in dnl ( *"-std="*) ## user specified a std value already ;; dnl ( *) for i in []stds[]; do SXE_CHECK_COMPILER_FLAG([-std="${i}"], [ std="-std=${i}" save_CC="${CC}" CC="${CC} ${std}" SXE_CHECK_ANON_STRUCTS_DECL CC="${save_CC}" if test "${sxe_cv_have_anon_structs_decl}" \ = "yes"; then break fi ]) done AC_MSG_CHECKING([for preferred CC std]) AC_MSG_RESULT([${std}]) CC="${CC} ${std}" ## while we're at it, check for anon initialising too SXE_CHECK_ANON_STRUCTS_INIT ## oh and sloppy sloppy init SXE_CHECK_SLOPPY_STRUCTS_INIT ;; esac popdef([stds]) ])dnl SXE_CHECK_CC AC_DEFUN([SXE_CHECK_ANON_STRUCTS_INIT], [ AC_MSG_CHECKING([dnl whether C compiler can initialise anonymous structs and unions]) AC_LANG_PUSH([C]) ## backup our CFLAGS and unset it save_CFLAGS="${CFLAGS}" CFLAGS="" AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ union __test_u { int i; struct { char c; char padc; short int pads; }; }; ]], [[ union __test_u tmp = {.c = '4'}; ]])], [ sxe_cv_have_anon_structs_init="yes" ], [ sxe_cv_have_anon_structs_init="no" ]) AC_MSG_RESULT([${sxe_cv_have_anon_structs_init}]) ## restore CFLAGS CFLAGS="${save_CFLAGS}" if test "${sxe_cv_have_anon_structs_init}" = "yes"; then AC_DEFINE([HAVE_ANON_STRUCTS_INIT], [1], [dnl Whether c11 anon struct initialising works]) $1 : else $2 : fi AC_LANG_POP() ])dnl SXE_CHECK_ANON_STRUCTS_INIT AC_DEFUN([SXE_CHECK_ANON_STRUCTS_DECL], [ AC_MSG_CHECKING([dnl whether C compiler can understand anonymous structs and unions]) AC_LANG_PUSH([C]) ## backup our CFLAGS and unset it save_CFLAGS="${CFLAGS}" CFLAGS="" AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ union __test_u { int i; struct { char c; char padc; short int pads; }; }; ]], [[ /* nothing to do really*/ union __test_u foo; foo.c = 0; ]])], [ sxe_cv_have_anon_structs_decl="yes" ], [ sxe_cv_have_anon_structs_decl="no" ]) AC_MSG_RESULT([${sxe_cv_have_anon_structs_decl}]) ## restore CFLAGS CFLAGS="${save_CFLAGS}" if test "${sxe_cv_have_anon_structs_decl}" = "yes"; then AC_DEFINE([HAVE_ANON_STRUCTS_DECL], [1], [dnl Whether c11 anon structs declaring works]) $1 : else $2 : fi AC_LANG_POP() ])dnl SXE_CHECK_ANON_STRUCTS_DECL AC_DEFUN([SXE_CHECK_SLOPPY_STRUCTS_INIT], [ AC_LANG_PUSH([C]) ## backup our CFLAGS and unset it save_CFLAGS="${CFLAGS}" CFLAGS="-Werror" SXE_CHECK_COMPILER_FLAG([-Wmissing-field-initializers], [ CFLAGS="${CFLAGS} -Wmissing-field-initializers"]) AC_MSG_CHECKING([dnl whether C compiler can initialise structs and unions in a sloppy way]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ struct __test_s { int i; int j; }; ]], [[ struct __test_s tmp = {}; ]])], [ sxe_cv_have_sloppy_structs_init="yes" ], [ sxe_cv_have_sloppy_structs_init="no" ]) AC_MSG_RESULT([${sxe_cv_have_sloppy_structs_init}]) ## restore CFLAGS CFLAGS="${save_CFLAGS}" if test "${sxe_cv_have_sloppy_structs_init}" = "yes"; then AC_DEFINE([HAVE_SLOPPY_STRUCTS_INIT], [1], [dnl Whether sloppy struct initialising works]) $1 : else $2 : fi AC_LANG_POP() ])dnl SXE_CHECK_SLOPPY_STRUCTS_INIT AC_DEFUN([SXE_CHECK_INTRINS], [dnl AC_CHECK_HEADERS([immintrin.h]) AC_CHECK_HEADERS([x86intrin.h]) AC_CHECK_HEADERS([ia32intrin.h]) AC_CHECK_HEADERS([popcntintrin.h]) AC_CHECK_TYPES([__m128i], [], [], [[ #if defined HAVE_X86INTRIN_H # include #elif defined HAVE_IMMINTRIN_H # include #endif ]]) AC_CHECK_TYPES([__m256i], [], [], [[ #if defined HAVE_X86INTRIN_H # include #elif defined HAVE_IMMINTRIN_H # include #endif ]]) AC_CHECK_TYPES([__m512i], [], [], [[ #if defined HAVE_X86INTRIN_H # include #elif defined HAVE_IMMINTRIN_H # include #endif ]]) AC_CHECK_TYPES([__mmask64], [], [], [[ #if defined HAVE_X86INTRIN_H # include #elif defined HAVE_IMMINTRIN_H # include #endif ]]) ])dnl SXE_CHECK_INTRINS AC_DEFUN([SXE_CHECK_SIMD], [dnl dnl Usage: SXE_CHECK_SIMD([INTRIN], [[SNIPPET], [IF-FOUND], [IF-NOT-FOUND]]) AC_REQUIRE([SXE_CHECK_INTRINS]) AC_MSG_CHECKING([for SIMD routine $1]) AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #if defined HAVE_IA32INTRIN_H # include #endif #if defined HAVE_X86INTRIN_H # include #endif #if defined HAVE_IMMINTRIN_H # include #endif #if defined HAVE_POPCNTINTRIN_H # include #endif ]], [ifelse([$2],[],[$1(0U)],[$2]);])], [ eval AS_TR_SH(ac_cv_func_$1)="yes" AC_DEFINE(AS_TR_CPP([HAVE_$1]), [1], [dnl Define to 1 if you have the `$1' simd routine]) $3 ], [ eval AS_TR_SH(ac_cv_func_$1)="no" $4 ]) AC_MSG_RESULT([${ac_cv_func_$1}]) ])dnl SXE_CHECK_SIMD AC_DEFUN([SXE_CHECK_CILK], [dnl dnl Usage: SXE_CHECK_CILK([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) dnl defines sxe_cv_feat_cilk to "yes" if applicable, "no" otherwise dnl also AC_DEFINEs HAVE_CILK AC_CHECK_HEADERS([cilk/cilk.h]) save_CFLAGS="${CFLAGS}" SXE_CHECK_COMPILER_FLAG([-fcilkplus], [CFLAGS="${CFLAGS} -fcilkplus"]) AC_MSG_CHECKING([whether Cilk+ keywords work]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #if defined HAVE_CILK_CILK_H # include #else /* !HAVE_CILK_CILK_H */ # define cilk_spawn _Cilk_spawn # define cilk_sync _Cilk_sync # define cilk_for _Cilk_for #endif /* HAVE_CILK_CILK_H */ static char *trick; static int pcmp(const void *x, const void *y) { return (const char*)x - (const char*)y; } ]], [ int x = 0; int j; cilk_spawn qsort(trick, 1, 2, pcmp); qsort(trick + 4, 1, 2, pcmp); cilk_sync; cilk_for(j = 0; j < 8; j++) { x++; } ])], [ AC_DEFINE([HAVE_CILK], [1], [define when compiler supports Cilk+ keywords]) sxe_cv_feat_cilk="yes" $1 ], [ CFLAGS="${save_CFLAGS}" sxe_cv_feat_cilk="no" $2 ]) AC_MSG_RESULT([${sxe_cv_feat_cilk}]) ])dnl SXE_CHECK_CILK dnl sxe-compiler.m4 ends here dateutils-0.4.5/m4/sxe-libtool.m4000066400000000000000000000031061335042257000165420ustar00rootroot00000000000000dnl sxe-libtool.m4 -- just a quick libtoolish macros dnl dnl Copyright (C) 2007-2016 Sebastian Freundt. dnl dnl This file is part of unserding AC_DEFUN([SXE_CHECK_LIBTOOL], [dnl AC_MSG_RESULT([starting libtool investigation...]) ## turn off -Werror'ing ac_[]_AC_LANG_ABBREV[]_werror_flag= LT_PREREQ([2.1]) LT_INIT([dlopen]) LT_LIB_DLLOAD LT_LIB_M LT_SYS_DLOPEN_DEPLIBS LT_SYS_SYMBOL_USCORE LT_FUNC_DLSYM_USCORE ## cope with libtool's convenience lib/bin concept if test -n "$lt_cv_objdir"; then ## this variable is a #define, too LT_OBJDIR="$lt_cv_objdir" else ## hm, probably not the best idea but let's try LT_OBJDIR="." fi ## definitely subst that though AC_SUBST([LT_OBJDIR]) ## currently there's no official variable for that, but `lt-' ## seems to be a consistent choice throughout all libtools LT_CONVENIENCE_PREFIX="lt-" AC_SUBST([LT_CONVENIENCE_PREFIX]) ## reset XCCFLAG, we KNOW it's XCClinker in libtool XCCFLAG="-XCClinker" ])dnl SXE_CHECK_LIBTOOL AC_DEFUN([SXE_CHECK_LIBLTDL], [dnl ## make sure the libtool stuff has been run before AC_REQUIRE([SXE_CHECK_LIBTOOL]) ## This can't be here because older versions of libtool ## seem to overlook the argument to LTDL_INIT ## put the next two lines into c.ac instead and then call this macro dnl LT_CONFIG_LTDL_DIR([libltdl]) dnl LTDL_INIT([recursive]) # workaround libtool LT_CONFIG_H bug #12262 AC_CONFIG_COMMANDS_PRE([LT_CONFIG_H=`expr "$LT_CONFIG_H" : '.*/\(.*\)'`]) AM_CONDITIONAL([DESCEND_LIBLTDL], [test "${with_included_ltdl}" = "yes"]) ])dnl SXE_CHECK_LIBLTDL dnl sxe-libtool.m4 ends here dateutils-0.4.5/m4/sxe-linker.m4000066400000000000000000000132421335042257000163640ustar00rootroot00000000000000dnl linker.m4 --- linker magic dnl dnl Copyright (C) 2005 - 2012 Sebastian Freundt dnl Copyright (c) 2005 Steven G. Johnson dnl Copyright (c) 2005 Matteo Frigo dnl dnl Author: Sebastian Freundt dnl dnl Redistribution and use in source and binary forms, with or without dnl modification, are permitted provided that the following conditions dnl are met: dnl dnl 1. Redistributions of source code must retain the above copyright dnl notice, this list of conditions and the following disclaimer. dnl dnl 2. Redistributions in binary form must reproduce the above copyright dnl notice, this list of conditions and the following disclaimer in the dnl documentation and/or other materials provided with the distribution. dnl dnl 3. Neither the name of the author nor the names of any contributors dnl may be used to endorse or promote products derived from this dnl software without specific prior written permission. dnl dnl THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR dnl IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED dnl WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE dnl DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE dnl FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR dnl CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF dnl SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR dnl BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, dnl WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE dnl OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN dnl IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. dnl dnl This file is part of SXEmacs. AC_DEFUN([SXE_CHECK_LINKER_FLAGS], [dnl dnl just like SXE_CHECK_COMPILER_FLAGS but calls the linker dnl SXE_CHECK_LINKER_FLAGS(, , , dnl ) AC_REQUIRE([SXE_CHECK_COMPILER_XFLAG]) AC_MSG_CHECKING([whether linker accepts $1]) dnl Some hackery here since AC_CACHE_VAL can't handle a non-literal varname: AC_LANG_WERROR([on]) AS_LITERAL_IF([$1], [ AC_CACHE_VAL(AS_TR_SH(sxe_cv_[]_AC_LANG_ABBREV[]_flags_$1), [ sxe_save_FLAGS=$[]_AC_LANG_PREFIX[]FLAGS _AC_LANG_PREFIX[]FLAGS="$4 ${XFLAG} $1" AC_LINK_IFELSE([AC_LANG_PROGRAM()], AS_TR_SH(sxe_cv_[]_AC_LANG_ABBREV[]_flags_$1)="yes", AS_TR_SH(sxe_cv_[]_AC_LANG_ABBREV[]_flags_$1)="no") _AC_LANG_PREFIX[]FLAGS=$sxe_save_FLAGS])], [ sxe_save_FLAGS=$[]_AC_LANG_PREFIX[]FLAGS _AC_LANG_PREFIX[]FLAGS="$4 ${XFLAG} $1" AC_LINK_IFELSE([AC_LANG_PROGRAM()], eval AS_TR_SH(sxe_cv_[]_AC_LANG_ABBREV[]_flags_$1)="yes", eval AS_TR_SH(sxe_cv_[]_AC_LANG_ABBREV[]_flags_$1)="no") _AC_LANG_PREFIX[]FLAGS=$sxe_save_FLAGS]) eval sxe_check_linker_flags=$AS_TR_SH(sxe_cv_[]_AC_LANG_ABBREV[]_flags_$1) AC_LANG_WERROR([off]) AC_MSG_RESULT([$sxe_check_linker_flags]) if test "$sxe_check_linker_flags" = "yes"; then m4_default([$2], :) else m4_default([$3], :) fi ])dnl SXE_CHECK_LINKER_FLAGS AC_DEFUN([SXE_CHECK_LD_ZFLAG], [dnl pushdef([LD_ZFLAG], [$1]) pushdef([cv_zflag], [sxe_cv_ld__z_]translit(LD_ZFLAG,[-.=],[___])) SXE_CHECK_LINKER_FLAGS([-z ]LD_ZFLAG[]) dnl Use the check that actually calls the compiler/linker to examine the flags dnl AC_CACHE_CHECK([whether linker supports -z ]LD_ZFLAG[], dnl []cv_zflag[], [_SXE_CHECK_LD_ZFLAG(LD_ZFLAG)]) popdef([cv_zflag]) popdef([LD_ZFLAG]) ])dnl SXE_CHECK_LD_ZFLAG AC_DEFUN([_SXE_CHECK_LD_ZFLAG], [dnl ## arg1 is the flag to check for pushdef([LD_ZFLAG], [$1]) pushdef([cv_zflag], [sxe_cv_ld__z_]translit(LD_ZFLAG,[-.=],[___])) if test "$GCC" = "yes"; then if test "($CC -Xlinker --help 2>&1 | \ grep \"-z []LD_ZFLAG[]\" > /dev/null 2>&1 ) "; then cv_zflag="yes" else cv_zflag="no" fi elif test -n "$LD"; then if test "($LD --help 2>&1 | \ grep \"-z []LD_ZFLAG[]\" > /dev/null 2>&1 )"; then cv_zflag="yes" else cv_zflag="no" fi else cv_zflag="no" fi popdef([cv_zflag]) popdef([LD_ZFLAG]) ])dnl _SXE_CHECK_LD_ZFLAG AC_DEFUN([SXE_LD_EXPORT_DYNAMIC], [dnl SXE_CHECK_LINKER_FLAGS([-export-dynamic], [ LD_EXPORT_DYNAMIC="-export-dynamic" ]) AC_SUBST([LD_EXPORT_DYNAMIC]) ])dnl SXE_LD_EXPORT_DYNAMIC AC_DEFUN([SXE_CHECK_LDFLAGS], [dnl AC_REQUIRE([SXE_CHECK_COMPILER_XFLAG]) ## relocation SXE_CHECK_LD_ZFLAG([combreloc]) SXE_CHECK_LD_ZFLAG([nocombreloc]) ## symbols SXE_CHECK_LD_ZFLAG([defs]) SXE_CHECK_LD_ZFLAG([muldefs]) ## search paths SXE_CHECK_LD_ZFLAG([nodefaultlib]) ## binding policy SXE_CHECK_LD_ZFLAG([lazy]) SXE_CHECK_LD_ZFLAG([now]) SXE_LD_EXPORT_DYNAMIC LDFLAGS="${ldflags} ${ac_cv_env_LDFLAGS_value}" AC_MSG_CHECKING([for preferred LDFLAGS]) AC_MSG_RESULT([${LDFLAGS}]) AC_MSG_NOTICE([ If you wish to ADD your own flags you want to stop here and rerun the configure script like so: configure LDFLAGS= You can always override the determined LDFLAGS, partially or totally, using make -C LDFLAGS= [target] or make LDFLAGS= [target] respectively NOTE: -C option is not available on all systems ]) ])dnl SXE_CHECK_LDFLAGS AC_DEFUN([SXE_PREPEND_LINKER_FLAG], [dnl ## a convenience function to add such linker flags to variables ## arg1 is the flag to add (must include -z if applicable) ## arg2 is the variable whither to prepend pushdef([FLAG], [$1]) pushdef([__FLAG], [-Wl,]patsubst([$1], [ ], [[,]])) pushdef([VAR], [$2]) []VAR[]="[]__FLAG[] $[]VAR[]" if test "$extra_verbose" = "yes"; then echo " Prepending linker flag \"[]__FLAG[]\" to \$[]VAR[]" fi popdef([VAR]) popdef([__FLAG]) popdef([FLAG]) ])dnl SXE_PREPEND_LINKER_FLAG dnl sxe-linker.m4 ends here dateutils-0.4.5/m4/sxe-matlab.m4000066400000000000000000000063011335042257000163360ustar00rootroot00000000000000## first parameter may point to a matlab root or the matlab binary AC_DEFUN([SXE_CHECK_MATLAB], [dnl foo=`mktemp /tmp/sxe_check_matlab.XXXXXXXXXX` AC_ARG_VAR([MATLAB], [full path to matlab binary]) sxe_cv_matlab="${MATLAB:-matlab}" AC_ARG_VAR([MATLABPATH], [path to matlab toolboxes]) sxe_cv_matlabpath="${MATLABPATH:-no}" AC_MSG_CHECKING([for matlab root]) ## assume no matlab sxe_cv_matlabroot="no" "${sxe_cv_matlab}" -e 2>/dev/null | grep "MATLAB" > "${foo}" ## source that source "${foo}" MATLABROOT="${MATLAB}" AC_SUBST([MATLABROOT]) AC_MSG_RESULT([${MATLABROOT}]) AC_MSG_CHECKING([for matlab toolbox path]) if test -z "${sxe_cv_matlabpath}" \ -o "${sxe_cv_matlabpath}" = "no"; then MATLABORIGPATH="${MATLABPATH}" else MATLABORIGPATH="${MATLABPATH}" MATLABPATH="${sxe_cv_matlabpath}" fi AC_SUBST([MATLABORIGPATH]) AC_SUBST([MATLABPATH]) AC_MSG_RESULT([${MATLABPATH}]) AC_MSG_CHECKING([for matlab mex file extension]) sxe_cv_mexext=`"${MATLABROOT}/bin/mexext" 2>/dev/null` MEXEXT="${sxe_cv_mexext:-mex}" AC_SUBST([MEXEXT]) AC_MSG_RESULT([${sxe_cv_mexext:-mex (assumed)}]) ## now reset *our* idea of what MATLAB should be MATLAB="${sxe_cv_matlab}" AC_ARG_VAR([matlab_CFLAGS], [include directives for matlab headers]) if test -n "${matlab_CFLAGS}"; then : elif test -z "${MATLABROOT}"; then ## big cluster fuck : else matlab_CFLAGS="-I${MATLABROOT}/extern/include" fi if test -n "${matlab_CFLAGS}"; then save_CPPFLAGS="${CPPFLAGS}" CPPFLAGS="${CPPFLAGS} ${matlab_CFLAGS}" AC_CHECK_HEADER([mex.h]) sxe_cv_matlab_mex_h="${ac_cv_header_mex_h}" unset ac_cv_header_mex_h CPPFLAGS="${save_CPPFLAGS}" fi rm -f -- "${foo}" ])dnl SXE_CHECK_MATLAB AC_DEFUN([SXE_CHECK_OCTAVE], [dnl ## mimic pkg-config AC_ARG_VAR([octave_CFLAGS], [include directives for matlab headers]) AC_ARG_VAR([octave_LIBS], [library directives for octave linking]) AC_ARG_VAR([OCTAVEPATH], [path to octave toolboxes]) sxe_cv_octavepath="${OCTAVEPATH:-no}" ## prep the octave extension path, this is twofold AC_PATH_PROG([OCTAVE_CONFIG], [octave-config]) if test -n "${OCTAVE_CONFIG}"; then octave_CFLAGS=-I`"${OCTAVE_CONFIG}" -p OCTINCLUDEDIR` octave_LIBS=-L`"${OCTAVE_CONFIG}" -p OCTLIBDIR` AC_MSG_CHECKING([for octave toolbox path]) OCTAVEORIGPATH=`"${OCTAVE_CONFIG}" -p LOCALOCTFILEDIR` OCTAVELIBDIR=`"${OCTAVE_CONFIG}" -p LIBDIR` OCTAVEPATH=`echo "${OCTAVEORIGPATH#${OCTAVELIBDIR}}"` if test "${OCTAVEPATH}" = "${OCTAVEORIGPATH}"; then : elif test -z "${sxe_cv_octavepath}" \ -o "${sxe_cv_octavepath}" = "no"; then ## we did substitute then innit? OCTAVEPATH="\${libdir}${OCTAVEPATH}" fi AC_SUBST([OCTAVEPATH]) AC_SUBST([OCTAVEORIGPATH]) AC_MSG_RESULT([${OCTAVEPATH}]) fi save_CPPFLAGS="${CPPFLAGS}" CPPFLAGS="${CPPFLAGS} ${octave_CFLAGS}" AC_CHECK_HEADERS([mex.h]) AC_CHECK_HEADERS([octave/mex.h]) if test "${ac_cv_header_mex_h}" = "yes"; then sxe_cv_octave_mex_h="yes" elif test "${ac_cv_header_octave_mex_h}" = "yes"; then sxe_cv_octave_mex_h="yes" fi unset ac_cv_header_mex_h CPPFLAGS="${save_CPPFLAGS}" if test "${sxe_cv_octave_mex_h}" = "yes"; then have_octave="yes" else have_octave="no" fi ])dnl SXE_CHECK_OCTAVE dnl sxe-matlab.m4 ends here dateutils-0.4.5/m4/sxe-mmap.m4000066400000000000000000000035411335042257000160330ustar00rootroot00000000000000AC_DEFUN([SXE_CHECK_SYS_MMAN], [dnl AC_CHECK_HEADERS([sys/mman.h]) ])dnl SXE_CHECK_SYS_MMAN AC_DEFUN([SXE_CHECK_MAP_ANON], [dnl AC_MSG_CHECKING([for ANON maps]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #define _POSIX_C_SOURCE 200112L #define _XOPEN_SOURCE 600 #define _BSD_SOURCE #if defined HAVE_SYS_MMAN_H # include #endif /* HAVE_SYS_MMAN_H */ #if defined MAP_ANON /* good */ #elif defined MAP_ANONYMOUS /* good too */ #else # error MAP_ANON | MAP_ANONYMOUS needed #endif ]])], [sxe_cv_feat_anon_maps="yes"], [sxe_cv_feat_anon_maps="no"]) if test "${sxe_cv_feat_anon_maps}" = "no"; then AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #define _POSIX_C_SOURCE 200112L #define _BSD_SOURCE #define _XOPEN_SOURCE 600 #define _ALL_SOURCE #if defined HAVE_SYS_MMAN_H # include #endif /* HAVE_SYS_MMAN_H */ #if defined MAP_ANON /* good */ #elif defined MAP_ANONYMOUS /* good too */ #else # error MAP_ANON | MAP_ANONYMOUS needed #endif ]])], [ sxe_cv_feat_anon_maps="yes" AC_DEFINE([MAP_ANON_NEEDS_ALL_SOURCE], [1], [MAP_ANON with _ALL_SOURCE]) ], [ sxe_cv_feat_anon_maps="no" ]) fi if test "${sxe_cv_feat_anon_maps}" = "no"; then AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #define _POSIX_C_SOURCE 200112L #define _BSD_SOURCE #define _XOPEN_SOURCE 600 #define _DARWIN_C_SOURCE #if defined HAVE_SYS_MMAN_H # include #endif /* HAVE_SYS_MMAN_H */ #if defined MAP_ANON /* good */ #elif defined MAP_ANONYMOUS /* good too */ #else # error MAP_ANON | MAP_ANONYMOUS needed #endif ]])], [ sxe_cv_feat_anon_maps="yes" AC_DEFINE([MAP_ANON_NEEDS_DARWIN_SOURCE], [1], [MAP_ANON with _DARWIN_C_SOURCE]) ], [ sxe_cv_feat_anon_maps="no" ]) fi AC_MSG_RESULT([${sxe_cv_feat_anon_maps}]) ])dnl SXE_CHECK_MAP_ANON AC_DEFUN([SXE_CHECK_MMAP], [dnl AC_REQUIRE([SXE_CHECK_SYS_MMAN]) AC_REQUIRE([SXE_CHECK_MAP_ANON]) ])dnl SXE_CHECK_MMAP dateutils-0.4.5/m4/yuck.m4000066400000000000000000000131721335042257000152600ustar00rootroot00000000000000dnl yuck.m4 --- yuck goodies dnl dnl Copyright (C) 2013-2016 Sebastian Freundt dnl dnl Author: Sebastian Freundt dnl dnl Redistribution and use in source and binary forms, with or without dnl modification, are permitted provided that the following conditions dnl are met: dnl dnl 1. Redistributions of source code must retain the above copyright dnl notice, this list of conditions and the following disclaimer. dnl dnl 2. Redistributions in binary form must reproduce the above copyright dnl notice, this list of conditions and the following disclaimer in the dnl documentation and/or other materials provided with the distribution. dnl dnl 3. Neither the name of the author nor the names of any contributors dnl may be used to endorse or promote products derived from this dnl software without specific prior written permission. dnl dnl THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR dnl IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED dnl WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE dnl DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE dnl FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR dnl CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF dnl SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR dnl BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, dnl WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE dnl OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN dnl IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. dnl dnl This file is part of yuck. AC_DEFUN([AX_CHECK_M4_BUFFERS], [dnl AC_MSG_CHECKING([for m4 with sufficient capabilities]) AC_ARG_VAR([M4], [full path to the m4 tool]) probe_M4="${M4-m4}" if ${probe_M4} >/dev/null 2>&1 \ -Dx='y y y y y y y y y y y y y y y y' \ -Dy='z z z z z z z z z z z z z z z z' \ -Dz='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0' <<'EOF' [define(`foo', x)] EOF then ## ah well done AC_MSG_RESULT([${probe_M4}]) M4="${probe_M4}" else ## check if a little buffer massage solves the problem probe_M4="${M4-m4} -B16384" if ${probe_M4} >/dev/null 2>&1 \ -Dx='y y y y y y y y y y y y y y y y' \ -Dy='z z z z z z z z z z z z z z z z' \ -Dz='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0' <<'EOF' [define(`foo', x)] EOF then ## very well then, let's use -B AC_MSG_RESULT([${probe_M4}]) M4="${probe_M4}" else AC_MSG_WARN([m4 on this machine might suffer from big buffers.]) M4="${M4-m4}" fi fi AC_DEFINE_UNQUOTED([YUCK_M4], ["${M4}"], [m4 value used for yuck build]) ])dnl AX_CHECK_M4_BUFFERS AC_DEFUN([AX_CHECK_YUCK], [dnl AC_ARG_WITH([included-yuck], [dnl AS_HELP_STRING([--with-included-yuck], [ Use included copy of the yuck command line parser generator instead of the system-wide one.])], [with_included_yuck="${withval}"], [$1]) AC_REQUIRE([AX_CHECK_M4_BUFFERS]) if test "${with_included_yuck}" != "yes"; then AC_PATH_PROG([YUCK], [yuck]) AC_ARG_VAR([YUCK], [full path to the yuck tool]) if test -n "${YUCK}"; then ## see what m4 they used back then YUCK_M4=`${YUCK} config --m4 2>/dev/null` M4="${YUCK_M4-$M4}" fi fi AM_CONDITIONAL([HAVE_YUCK], [dnl test "${with_included_yuck}" != "yes" -a -n "${YUCK}"]) ## further requirement is either getline() or fgetln() AC_CHECK_FUNCS([getline]) AC_CHECK_FUNCS([fgetln]) ])dnl AX_CHECK_YUCK AC_DEFUN([AX_YUCK_SCMVER], [dnl ## initially generate version.mk and yuck.version here ## because only GNU make can do this at make time pushdef([vfile], [$1]) AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT]) AC_LANG_PUSH([C]) AC_PROG_CC_C99 ## use our yuck-scmver tool AC_MSG_CHECKING([for stipulated version files]) save_CPPFLAGS="${CPPFLAGS}" CPPFLAGS="-I${srcdir}/src -I${ac_aux_dir} ${CPPFLAGS}" AC_RUN_IFELSE([AC_LANG_SOURCE([[ #define CONFIGURE #define _XOPEN_SOURCE 600 #define VERSION_FILE "${srcdir}/.version" #include "yuck-scmver.c" ]])], [STIP_VERSION=`./conftest$EXEEXT`], [AC_MSG_RESULT([none])], [dnl AC_MSG_RESULT([impossible, cross-compiling]) if test -f "[]vfile[]" -o \ -f "${srcdir}/[]vfile[]" -o \ -f "${srcdir}/.version"; then AC_MSG_NOTICE([ Files that (possibly) mandate versions have been detected. These are `]vfile[' or `${srcdir}/]vfile[' or `${srcdir}/.version'. However, their contents cannot be automatically checked for integrity due to building for a platform other than the current one (cross-compiling). I will proceed with the most conservative guess for the stipulated version, which is `${VERSION}'. If that appears to be wrong, or needs overriding, please edit the aforementioned files manually. Also note, even though this project comes with all the tools to perform a successful bootstrap for any of the files above, should they go out of date or be deleted, they don't support cross-builds. ]) fi ]) CPPFLAGS="${save_CPPFLAGS}" AC_LANG_POP([C]) if test -n "${STIP_VERSION}"; then VERSION="${STIP_VERSION}" fi ## also massage version.mk file if test -f "[]vfile[]" -a ! -w "[]vfile[]"; then : elif test -f "${srcdir}/[]vfile[]"; then ## make sure it's in the builddir as well cp -p "${srcdir}/[]vfile[]" "[]vfile[]" 2>/dev/null elif test -f "${srcdir}/[]vfile[].in"; then ${M4-m4} -DYUCK_SCMVER_VERSION="${VERSION}" \ "${srcdir}/[]vfile[].in" > "[]vfile[]" else echo "VERSION = ${VERSION}" > "[]vfile[]" fi ## make sure .version is generated (for version.mk target in GNUmakefile) if test -f "${srcdir}/.version"; then cp -p "${srcdir}/.version" ".version" 2>/dev/null else echo "v${VERSION}" > ".version" 2>/dev/null fi popdef([vfile]) ])dnl AX_YUCK_SCMVER dnl yuck.m4 ends here dateutils-0.4.5/src/000077500000000000000000000000001335042257000143065ustar00rootroot00000000000000dateutils-0.4.5/src/Makefile.am000066400000000000000000000120171335042257000163430ustar00rootroot00000000000000### Makefile.am include $(top_builddir)/version.mk AM_CFLAGS = $(EXTRA_CFLAGS) AM_CPPFLAGS = -D_POSIX_C_SOURCE=200112L -D_XOPEN_SOURCE=600 -D_BSD_SOURCE AM_CPPFLAGS += -DHAVE_VERSION_H AM_LDFLAGS = AM_YFLAGS = -d M4 = m4 bin_PROGRAMS = noinst_PROGRAMS = noinst_HEADERS = noinst_LIBRARIES = BUILT_SOURCES = CLEANFILES = GGO_HELPERS = EXTRA_DIST = $(BUILT_SOURCES) $(GGO_HELPERS) SUFFIXES = DT_INCLUDES = -I$(top_srcdir)/lib -I$(top_builddir)/lib DT_LIBS = $(top_builddir)/lib/libdut.a ANALYZE = clang ANALYZE_FLAGS = "--analyze" # Based on COMPILE target ANALYZE_COMMAND = $(ANALYZE) \ $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(DT_INCLUDES) $(AM_CFLAGS) $(CFLAGS) \ $(ANALYZE_FLAGS) noinst_LIBRARIES += libdutio.a libdutio_a_SOURCES = libdutio_a_SOURCES += dt-io.c dt-io.h libdutio_a_SOURCES += dt-io-zone.c dt-io-zone.h libdutio_a_SOURCES += alist.c alist.h libdutio_a_SOURCES += prchunk.c prchunk.h libdutio_a_SOURCES += dexpr.h libdutio_a_CPPFLAGS = $(AM_CPPFLAGS) libdutio_a_CPPFLAGS += $(DT_INCLUDES) libdutio_a_CPPFLAGS += -DTZMAP_DIR='"$(pkgdatadir)"' EXTRA_DIST += strpdt-special.gperf BUILT_SOURCES += strpdt-special.c ## all them binaries, alphabetical bin_PROGRAMS += dadd bin_PROGRAMS += dconv bin_PROGRAMS += ddiff bin_PROGRAMS += dgrep bin_PROGRAMS += dround bin_PROGRAMS += dseq bin_PROGRAMS += dsort bin_PROGRAMS += dtest bin_PROGRAMS += dzone if WITH_OLD_LINKS CREATE_OLD_LINKS = $(LN_S) date$$prog$(EXEEXT) d$$prog$(EXEEXT); endif if !WITH_OLD_NAMES install-exec-hook: cd $(DESTDIR)$(bindir) && \ for prog in add conv diff grep round seq sort test zone; do \ mv -f d$$prog$(EXEEXT) date$$prog$(EXEEXT) ; \ $(CREATE_OLD_LINKS) \ done uninstall-hook: cd $(DESTDIR)$(bindir) && \ for prog in add conv diff grep round seq sort test zone; do \ $(RM) date$$prog$(EXEEXT) ; \ done endif ## !WITH_OLD_NAMES dseq_SOURCES = dseq.c dseq.yuck dseq_CPPFLAGS = $(AM_CPPFLAGS) $(DT_INCLUDES) dseq_LDFLAGS = $(AM_LDFLAGS) dseq_LDADD = libdutio.a dseq_LDADD += $(DT_LIBS) BUILT_SOURCES += dseq.yucc if HAVE_STRPTIME bin_PROGRAMS += strptime strptime_SOURCES = strptime.c strptime.yuck strptime_CPPFLAGS = $(AM_CPPFLAGS) $(DT_INCLUDES) strptime_LDFLAGS = $(AM_LDFLAGS) strptime_LDADD = libdutio.a strptime_LDADD += $(DT_LIBS) endif BUILT_SOURCES += strptime.yucc dconv_SOURCES = dconv.c dconv.yuck dconv_CPPFLAGS = $(AM_CPPFLAGS) $(DT_INCLUDES) dconv_LDFLAGS = $(AM_LDFLAGS) dconv_LDADD = libdutio.a dconv_LDADD += $(DT_LIBS) BUILT_SOURCES += dconv.yucc dtest_SOURCES = dtest.c dtest.yuck dtest_CPPFLAGS = $(AM_CPPFLAGS) $(DT_INCLUDES) dtest_LDFLAGS = $(AM_LDFLAGS) dtest_LDADD = libdutio.a dtest_LDADD += $(DT_LIBS) BUILT_SOURCES += dtest.yucc dadd_SOURCES = dadd.c dadd.yuck dadd_CPPFLAGS = $(AM_CPPFLAGS) $(DT_INCLUDES) dadd_LDFLAGS = $(AM_LDFLAGS) dadd_LDADD = libdutio.a dadd_LDADD += $(DT_LIBS) BUILT_SOURCES += dadd.yucc ddiff_SOURCES = ddiff.c ddiff.yuck ddiff_CPPFLAGS = $(AM_CPPFLAGS) $(DT_INCLUDES) ddiff_LDFLAGS = $(AM_LDFLAGS) ddiff_LDADD = libdutio.a ddiff_LDADD += $(DT_LIBS) BUILT_SOURCES += ddiff.yucc dgrep_SOURCES = dgrep.c dgrep.yuck dgrep_CPPFLAGS = $(AM_CPPFLAGS) $(DT_INCLUDES) dgrep_LDFLAGS = $(AM_LDFLAGS) dgrep_LDADD = libdutio.a dgrep_LDADD += $(DT_LIBS) BUILT_SOURCES += dgrep.yucc dround_SOURCES = dround.c dround.yuck dround_CPPFLAGS = $(AM_CPPFLAGS) $(DT_INCLUDES) dround_LDFLAGS = $(AM_LDFLAGS) dround_LDADD = libdutio.a dround_LDADD += $(DT_LIBS) BUILT_SOURCES += dround.yucc dzone_SOURCES = dzone.c dzone.yuck dzone_CPPFLAGS = $(AM_CPPFLAGS) $(DT_INCLUDES) dzone_LDFLAGS = $(AM_LDFLAGS) dzone_LDADD = libdutio.a dzone_LDADD += $(DT_LIBS) BUILT_SOURCES += dzone.yucc dsort_SOURCES = dsort.c dsort.yuck dsort_CPPFLAGS = $(AM_CPPFLAGS) $(DT_INCLUDES) dsort_LDFLAGS = $(AM_LDFLAGS) dsort_LDADD = libdutio.a dsort_LDADD += $(DT_LIBS) BUILT_SOURCES += dsort.yucc if BUILD_DEXPR noinst_PROGRAMS += dexpr dexpr_SOURCES = dexpr.c dexpr_SOURCES += dexpr-scanner.l dexpr_SOURCES += dexpr-parser.y dexpr_CPPFLAGS = $(AM_CPPFLAGS) $(DT_INCLUDES) -DSTANDALONE dexpr_LDFLAGS = $(AM_LDFLAGS) dexpr_LDADD = libdutio.a dexpr_LDADD += $(DT_LIBS) endif ## BUILD_DEXPR BUILT_SOURCES += dexpr-scanner.c dexpr-parser.c dexpr-parser.h ## yuck rule SUFFIXES += .yuck SUFFIXES += .yucc .yuck.yucc: $(AM_V_GEN) PATH=$(top_builddir)/build-aux:"$${PATH}" \ yuck$(EXEEXT) gen -o $@ $< ## gperf rule SUFFIXES += .gperf .gperf.c: $(AM_V_GEN) $(GPERF) -L ANSI-C $< --output-file $@ ## just for parallel builds dexpr-parser.h: dexpr-parser.c # # Help the developers get nice post-processed source files ## Create preprocessor output (debugging purposes only) .c.i: $(COMPILE) -E -o $@ $< ## Create assembler output (debugging purposes only) .c.s: $(COMPILE) -S -c $(AM_CFLAGS) $< ## Run Clang static analyzer over sources. anal: $(SOURCES) @list='$(SOURCES)'; \ result=0; \ for file in $$list; do \ if echo $$file | grep '\.c$$' >/dev/null 2>&1; then \ echo "Analyzing $$file"; \ $(ANALYZE_COMMAND) $(srcdir)/$$file; \ status=$$?; \ if test $$status != 0; then \ result=1; \ fi; \ fi; \ done; \ set -e; exit $$result dateutils-0.4.5/src/alist.c000066400000000000000000000104541335042257000155720ustar00rootroot00000000000000/*** alist.c -- bog standard associative lists * * Copyright (C) 2010-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of dateutils. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***/ #if defined HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include #include #include #include #include "alist.h" #include "nifty.h" /* our alist is a simple flat char array with pointers behind every key * aligned to void* boundaries. */ static const void** __assoc(alist_t al, const char *key) { for (const char *ap = al->data, *const ep = ap + al->dend; ap < ep;) { const char *kp; const void **res = (const void**)al->data; /* unrolled strcmp */ for (kp = key; *ap && *ap == *kp; ap++, kp++); /* fast forward to void** boundary */ res += (ap - al->data) / sizeof(res) + 1U; if (*ap == *kp) { /* match! invariant: ap == kp == '\0' */ return res; } else if (*ap) { /* fast forward in void** increments */ for (; ((const char*)res)[-1]; res++); } /* skip over ptr, start again */ ap = (const char*)++res; } return NULL; } static bool __fitsp(alist_t al, size_t keylen) { return al->dend + keylen + 2 * sizeof(void**) < al->allz; } static int __chk_resz(alist_t al, size_t keylen) { if (UNLIKELY(!__fitsp(al, keylen))) { size_t ol = al->allz; void *tmp; al->allz = (al->allz * 2U) ?: 64U; if (UNLIKELY((tmp = realloc(al->data, al->allz)) == NULL)) { free_alist(al); return -1; } al->data = tmp; memset(al->data + ol, 0, al->allz - ol); } return 0; } /* public api */ void free_alist(alist_t al) { if (LIKELY(al->data != NULL)) { free(al->data); memset(al, 0, sizeof(*al)); } return; } const void* alist_assoc(alist_t al, const char *key) { const void **res; if (UNLIKELY(al->data == NULL)) { goto nada; } else if ((res = __assoc(al, key)) == NULL) { goto nada; } return *res; nada: return NULL; } void alist_put(alist_t al, const char *key, const void *val) { size_t klen = strlen(key); __chk_resz(al, klen); memcpy(al->data + al->dend, key, klen); /* round up to void** boundary */ with (const void **data = (const void**)al->data) { data += (al->dend + klen) / sizeof(data) + 1U; *data++ = val; al->dend = (const char*)data - al->data; } return; } void alist_set(alist_t al, const char *key, const void *val) { const void **ass; if ((ass = __assoc(al, key)) != NULL) { *ass = val; return; } alist_put(al, key, val); return; } acons_t alist_next(alist_t al) { acons_t res; if (UNLIKELY((const char*)al->iter >= al->data + al->dend)) { al->iter = NULL; res = (acons_t){NULL, NULL}; } else { const char *p = al->iter ?: al->data; size_t klen = strlen(p); with (const void *const *d = (const void*)p) { d += klen / sizeof(d) + 1U; res.key = p; res.val = *d++; al->iter = d; } } return res; } /* alist.c ends here */ dateutils-0.4.5/src/alist.h000066400000000000000000000050131335042257000155720ustar00rootroot00000000000000/*** alist.h -- bog standard associative lists * * Copyright (C) 2010-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of dateutils. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***/ #if !defined INCLUDED_alist_h_ #define INCLUDED_alist_h_ typedef struct alist_s *alist_t; typedef struct acons_s acons_t; struct alist_s { char *data; size_t allz; /* private slots */ size_t dend; const void *iter; }; struct acons_s { const char *key; const void *val; }; extern void free_alist(alist_t); /** * Return value associated with KEY in alist, or NULL if none found. */ extern const void *alist_assoc(alist_t, const char *key); /** * Put VAL as value associated with KEY in alist, but don't do a check * for duplicates first, i.e. it is assumed that KEY is not present. */ extern void alist_put(alist_t, const char *key, const void *val); /** * Set value associated with KEY in alist to VAL. */ extern void alist_set(alist_t, const char *key, const void *val); /** * Return next alist cons cell. */ extern acons_t alist_next(alist_t); #endif /* INCLUDED_alist_h_ */ dateutils-0.4.5/src/dadd.c000066400000000000000000000234171335042257000153550ustar00rootroot00000000000000/*** dadd.c -- perform simple date arithmetic, date plus duration * * Copyright (C) 2011-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of dateutils. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * **/ #if defined HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include "dt-core.h" #include "dt-io.h" #include "dt-core-tz-glue.h" #include "dt-locale.h" #include "prchunk.h" const char *prog = "dadd"; static bool durs_only_d_p(struct dt_dtdur_s dur[], size_t ndur) { for (size_t i = 0; i < ndur; i++) { if (dur[i].durtyp >= (dt_dtdurtyp_t)DT_NDURTYP) { return false; } } return true; } static struct dt_dt_s dadd_add(struct dt_dt_s d, struct dt_dtdur_s dur[], size_t ndur) { for (size_t i = 0; i < ndur; i++) { d = dt_dtadd(d, dur[i]); } return d; } struct mass_add_clo_s { void *pctx; const struct grep_atom_soa_s *gra; struct __strpdtdur_st_s st; struct dt_dt_s rd; zif_t fromz; zif_t hackz; zif_t z; const char *ofmt; int sed_mode_p; int quietp; }; static int proc_line(const struct mass_add_clo_s *clo, char *line, size_t llen) { struct dt_dt_s d; char *sp = NULL; char *ep = NULL; int rc = 0; do { /* check if line matches, */ d = dt_io_find_strpdt2( line, llen, clo->gra, &sp, &ep, clo->fromz); if (!dt_unk_p(d)) { if (UNLIKELY(d.fix) && !clo->quietp) { rc = 2; } /* perform addition now */ d = dadd_add(d, clo->st.durs, clo->st.ndurs); if (clo->hackz == NULL && clo->fromz != NULL) { /* fixup zone */ d = dtz_forgetz(d, clo->fromz); } if (clo->sed_mode_p) { __io_write(line, sp - line, stdout); dt_io_write(d, clo->ofmt, clo->z, '\0'); llen -= (ep - line); line = ep; } else { dt_io_write(d, clo->ofmt, clo->z, '\n'); break; } } else if (clo->sed_mode_p) { line[llen] = '\n'; __io_write(line, llen + 1, stdout); break; } else { /* obviously unmatched, warn about it in non -q mode */ if (!clo->quietp) { dt_io_warn_strpdt(line); rc = 2; } break; } } while (1); return rc; } static int mass_add_dur(const struct mass_add_clo_s *clo) { /* read lines from stdin * interpret as dates * add to reference duration * output */ size_t lno = 0; int rc = 0; for (char *line; prchunk_haslinep(clo->pctx); lno++) { size_t llen = prchunk_getline(clo->pctx, &line); rc |= proc_line(clo, line, llen); } return rc; } static int mass_add_d(const struct mass_add_clo_s *clo) { /* read lines from stdin * interpret as durations * add to reference date * output */ size_t lno = 0; struct dt_dt_s d; struct __strpdtdur_st_s st = __strpdtdur_st_initialiser(); int rc = 0; for (char *line; prchunk_haslinep(clo->pctx); lno++) { size_t llen; int has_dur_p = 1; llen = prchunk_getline(clo->pctx, &line); /* check for durations on this line */ do { if (dt_io_strpdtdur(&st, line) < 0) { has_dur_p = 0; } } while (__strpdtdur_more_p(&st)); /* finish with newline again */ line[llen] = '\n'; if (has_dur_p) { if (UNLIKELY(clo->rd.fix) && !clo->quietp) { rc = 2; } /* perform addition now */ d = dadd_add(clo->rd, st.durs, st.ndurs); if (clo->hackz == NULL && clo->fromz != NULL) { /* fixup zone */ d = dtz_forgetz(d, clo->fromz); } /* no sed mode here */ dt_io_write(d, clo->ofmt, clo->z, '\n'); } else if (clo->sed_mode_p) { __io_write(line, llen + 1, stdout); } else if (!clo->quietp) { line[llen] = '\0'; dt_io_warn_strpdt(line); rc = 2; } /* just reset the ndurs slot */ st.ndurs = 0; } /* free associated duration resources */ __strpdtdur_free(&st); return rc; } #include "dadd.yucc" int main(int argc, char *argv[]) { yuck_t argi[1U]; struct dt_dt_s d; struct __strpdtdur_st_s st = __strpdtdur_st_initialiser(); const char *ofmt; char **fmt; size_t nfmt; int rc = 0; bool dt_given_p = false; zif_t fromz = NULL; zif_t z = NULL; zif_t hackz = NULL; if (yuck_parse(argi, argc, argv)) { rc = 1; goto out; } else if (argi->nargs == 0) { error("Error: DATE or DURATION must be specified\n"); yuck_auto_help(argi); rc = 1; goto out; } /* init and unescape sequences, maybe */ ofmt = argi->format_arg; fmt = argi->input_format_args; nfmt = argi->input_format_nargs; if (argi->backslash_escapes_flag) { dt_io_unescape(argi->format_arg); for (size_t i = 0; i < nfmt; i++) { dt_io_unescape(fmt[i]); } } if (argi->from_locale_arg) { setilocale(argi->from_locale_arg); } if (argi->locale_arg) { setflocale(argi->locale_arg); } /* try and read the from and to time zones */ if (argi->from_zone_arg) { fromz = dt_io_zone(argi->from_zone_arg); } if (argi->zone_arg) { z = dt_io_zone(argi->zone_arg); } if (argi->base_arg) { struct dt_dt_s base = dt_strpdt(argi->base_arg, NULL, NULL); dt_set_base(base); } /* sanity checks, decide whether we're a mass date adder * or a mass duration adder, or both, a date and durations are * present on the command line */ with (const char *inp = argi->args[0U]) { /* date parsing needed postponing as we need to find out * about the durations */ if (!dt_unk_p(dt_io_strpdt(inp, fmt, nfmt, NULL))) { dt_given_p = true; } } /* check first arg, if it's a date the rest of the arguments are * durations, if not, dates must be read from stdin */ for (size_t i = dt_given_p; i < argi->nargs; i++) { const char *inp = argi->args[i]; do { if (dt_io_strpdtdur(&st, inp) < 0) { serror("Error: \ cannot parse duration string `%s'", st.istr); rc = 1; goto dur_out; } } while (__strpdtdur_more_p(&st)); } /* check if there's only d durations */ hackz = durs_only_d_p(st.durs, st.ndurs) ? NULL : fromz; /* read the first argument again in light of a completely parsed * duration sequence */ if (dt_given_p) { const char *inp = argi->args[0U]; if (dt_unk_p(d = dt_io_strpdt(inp, fmt, nfmt, hackz))) { error("\ Error: cannot interpret date/time string `%s'", inp); rc = 1; goto dur_out; } } /* start the actual work */ if (dt_given_p && st.ndurs) { if (!dt_unk_p(d = dadd_add(d, st.durs, st.ndurs))) { if (UNLIKELY(d.fix) && !argi->quiet_flag) { rc = 2; } if (hackz == NULL && fromz != NULL) { /* fixup zone */ d = dtz_forgetz(d, fromz); } dt_io_write(d, ofmt, z, '\n'); } else { rc = 1; } } else if (st.ndurs) { /* read dates from stdin */ struct grep_atom_s __nstk[16], *needle = __nstk; size_t nneedle = countof(__nstk); struct grep_atom_soa_s ndlsoa; struct mass_add_clo_s clo[1]; void *pctx; /* no threads reading this stream */ __io_setlocking_bycaller(stdout); /* lest we overflow the stack */ if (nfmt >= nneedle) { /* round to the nearest 8-multiple */ nneedle = (nfmt | 7) + 1; needle = calloc(nneedle, sizeof(*needle)); } /* and now build the needle */ ndlsoa = build_needle(needle, nneedle, fmt, nfmt); /* using the prchunk reader now */ if ((pctx = init_prchunk(STDIN_FILENO)) == NULL) { serror("could not open stdin"); goto ndl_free; } /* build the clo and then loop */ clo->pctx = pctx; clo->gra = &ndlsoa; clo->st = st; clo->fromz = fromz; clo->hackz = hackz; clo->z = z; clo->ofmt = ofmt; clo->sed_mode_p = argi->sed_mode_flag; clo->quietp = argi->quiet_flag; while (prchunk_fill(pctx) >= 0) { rc |= mass_add_dur(clo); } /* get rid of resources */ free_prchunk(pctx); ndl_free: if (needle != __nstk) { free(needle); } } else { /* mass-adding durations to reference date */ struct mass_add_clo_s clo[1]; void *pctx; /* no threads reading this stream */ __io_setlocking_bycaller(stdout); /* using the prchunk reader now */ if ((pctx = init_prchunk(STDIN_FILENO)) == NULL) { serror("could not open stdin"); goto dur_out; } /* build the clo and then loop */ clo->pctx = pctx; clo->rd = d; clo->fromz = fromz; clo->hackz = hackz; clo->z = z; clo->ofmt = ofmt; clo->sed_mode_p = argi->sed_mode_flag; clo->quietp = argi->quiet_flag; while (prchunk_fill(pctx) >= 0) { rc |= mass_add_d(clo); } /* get rid of resources */ free_prchunk(pctx); } dur_out: /* free the strpdur status */ __strpdtdur_free(&st); dt_io_clear_zones(); if (argi->from_locale_arg) { setilocale(NULL); } if (argi->locale_arg) { setflocale(NULL); } out: yuck_free(argi); return rc; } /* dadd.c ends here */ dateutils-0.4.5/src/dadd.yuck000066400000000000000000000062311335042257000161010ustar00rootroot00000000000000Usage: dateadd [OPTION]... [DATE/TIME] [DURATION] Add DURATION to DATE/TIME and print the result. If DATE/TIME is omitted but DURATION is given, read a list of DATE/TIMEs from stdin. If DURATION is omitted but DATE/TIME is given, read a list of DURATIONs from stdin. Durations are specified as nY, nMO, nW, or nD for years, months, weeks, or days respectively, or nH, nM, nS for hours, minutes, and seconds, where N is a (possibly negative) number. The unit symbols can be written lower-case as well (y, mo, w, d, h, m, s) and the unit symbol `d' can be omitted. Note that duration addition is not commutative! 2000-03-30 +1mo +1d -> 2000-05-01 2000-03-30 +1d +1mo -> 2000-04-30 -h, --help Print help and exit -V, --version Print version and exit -q, --quiet Suppress message about date/time and duration parser errors and fix-ups. The default is to print a warning or the fixed up value and return error code 2. -f, --format=STRING Output format. This can either be a specifier string (similar to strftime()'s FMT) or the name of a calendar. -i, --input-format=STRING... Input format, can be used multiple times. Each date/time will be passed to the input format parsers in the order they are given, if a date/time can be read successfully with a given input format specifier string, that value will be used. -b, --base=DT For underspecified input use DT as a fallback to fill in missing fields. Also used for ambiguous format specifiers to position their range on the absolute time line. Must be a date/time in ISO8601 format. If omitted defaults to the current date/time. -e, --backslash-escapes Enable interpretation of backslash escapes in the output and input format specifier strings. -S, --sed-mode Copy parts from the input before and after a matching date/time. Note that all occurrences of date/times within a line will be processed. --locale=LOCALE Format results according to LOCALE, this would only affect month and weekday names. --from-locale=LOCALE Interpret dates on stdin or the command line as coming from the locale LOCALE, this would only affect month and weekday names as input formats have to be specified explicitly. --from-zone=ZONE Interpret dates on stdin or the command line as coming from the time zone ZONE. -z, --zone=ZONE Convert dates printed on stdout to time zone ZONE, default: UTC. dateutils-0.4.5/src/dconv.c000066400000000000000000000127301335042257000155660ustar00rootroot00000000000000/*** dconv.c -- convert calendrical and time stamp systems * * Copyright (C) 2011-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of dateutils. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * **/ #if defined HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include "dt-core.h" #include "dt-io.h" #include "dt-locale.h" #include "prchunk.h" const char *prog = "dconv"; struct prln_ctx_s { struct grep_atom_soa_s *ndl; const char *ofmt; zif_t fromz; zif_t outz; int sed_mode_p; int quietp; }; static int proc_line(struct prln_ctx_s ctx, char *line, size_t llen) { struct dt_dt_s d; char *sp = NULL; char *ep = NULL; int rc = 0; do { d = dt_io_find_strpdt2( line, llen, ctx.ndl, &sp, &ep, ctx.fromz); /* check if line matches */ if (!dt_unk_p(d) && ctx.sed_mode_p) { __io_write(line, sp - line, stdout); dt_io_write(d, ctx.ofmt, ctx.outz, '\0'); llen -= (ep - line); line = ep; } else if (!dt_unk_p(d)) { if (UNLIKELY(d.fix) && !ctx.quietp) { rc = 2; } dt_io_write(d, ctx.ofmt, ctx.outz, '\n'); break; } else if (ctx.sed_mode_p) { line[llen] = '\n'; __io_write(line, llen + 1, stdout); break; } else { /* obviously unmatched, warn about it in non -q mode */ if (!ctx.quietp) { dt_io_warn_strpdt(line); rc = 2; } break; } } while (1); return rc; } #include "dconv.yucc" int main(int argc, char *argv[]) { yuck_t argi[1U]; const char *ofmt; char **fmt; size_t nfmt; int rc = 0; zif_t fromz = NULL; zif_t z = NULL; if (yuck_parse(argi, argc, argv)) { rc = 1; goto out; } /* init and unescape sequences, maybe */ ofmt = argi->format_arg; fmt = argi->input_format_args; nfmt = argi->input_format_nargs; if (argi->backslash_escapes_flag) { dt_io_unescape(argi->format_arg); for (size_t i = 0; i < nfmt; i++) { dt_io_unescape(fmt[i]); } } if (argi->locale_arg) { setflocale(argi->locale_arg); } if (argi->from_locale_arg) { setilocale(argi->from_locale_arg); } /* try and read the from and to time zones */ if (argi->from_zone_arg) { fromz = dt_io_zone(argi->from_zone_arg); } if (argi->zone_arg) { z = dt_io_zone(argi->zone_arg); } if (argi->base_arg) { struct dt_dt_s base = dt_strpdt(argi->base_arg, NULL, NULL); dt_set_base(base); } if (argi->nargs) { for (size_t i = 0; i < argi->nargs; i++) { const char *inp = argi->args[i]; struct dt_dt_s d = dt_io_strpdt(inp, fmt, nfmt, fromz); if (!dt_unk_p(d)) { if (UNLIKELY(d.fix) && !argi->quiet_flag) { rc = 2; } dt_io_write(d, ofmt, z, '\n'); } else if (!argi->quiet_flag) { rc = 2; dt_io_warn_strpdt(inp); } } } else { /* read from stdin */ size_t lno = 0; struct grep_atom_s __nstk[16], *needle = __nstk; size_t nneedle = countof(__nstk); struct grep_atom_soa_s ndlsoa; void *pctx; struct prln_ctx_s prln = { .ndl = &ndlsoa, .ofmt = ofmt, .fromz = fromz, .outz = z, .sed_mode_p = argi->sed_mode_flag, .quietp = argi->quiet_flag, }; /* no threads reading this stream */ __io_setlocking_bycaller(stdout); /* lest we overflow the stack */ if (nfmt >= nneedle) { /* round to the nearest 8-multiple */ nneedle = (nfmt | 7) + 1; needle = calloc(nneedle, sizeof(*needle)); } /* and now build the needles */ ndlsoa = build_needle(needle, nneedle, fmt, nfmt); /* using the prchunk reader now */ if ((pctx = init_prchunk(STDIN_FILENO)) == NULL) { serror("Error: could not open stdin"); goto ndl_free; } while (prchunk_fill(pctx) >= 0) { for (char *line; prchunk_haslinep(pctx); lno++) { size_t llen = prchunk_getline(pctx, &line); rc |= proc_line(prln, line, llen); } } /* get rid of resources */ free_prchunk(pctx); ndl_free: if (needle != __nstk) { free(needle); } } dt_io_clear_zones(); if (argi->from_locale_arg) { setilocale(NULL); } if (argi->locale_arg) { setflocale(NULL); } out: yuck_free(argi); return rc; } /* dconv.c ends here */ dateutils-0.4.5/src/dconv.yuck000066400000000000000000000057341335042257000163250ustar00rootroot00000000000000Usage: dateconv [OPTION]... [DATE/TIME]... Convert DATE/TIMEs between calendrical systems. If DATE/TIME is omitted date/times are read from stdin. DATE/TIME can also be one of the following specials - `now' interpreted as the current (UTC) time stamp - `time' the time part of the current (UTC) time stamp - `today' the current date (according to UTC) - `tomo[rrow]' tomorrow's date (according to UTC) - `y[ester]day' yesterday's date (according to UTC) -h, --help Print help and exit -V, --version Print version and exit -q, --quiet Suppress message about date/time and duration parser errors and fix-ups. The default is to print a warning or the fixed up value and return error code 2. -f, --format=STRING Output format. This can either be a specifier string (similar to strftime()'s FMT) or the name of a calendar. -i, --input-format=STRING... Input format, can be used multiple times. Each date/time will be passed to the input format parsers in the order they are given, if a date/time can be read successfully with a given input format specifier string, that value will be used. -b, --base=DT For underspecified input use DT as a fallback to fill in missing fields. Also used for ambiguous format specifiers to position their range on the absolute time line. Must be a date/time in ISO8601 format. If omitted defaults to the current date/time. -e, --backslash-escapes Enable interpretation of backslash escapes in the output and input format specifier strings. -S, --sed-mode Copy parts from the input before and after a matching date/time. Note that all occurrences of date/times within a line will be processed. --locale=LOCALE Format results according to LOCALE, this would only affect month and weekday names. --from-locale=LOCALE Interpret dates on stdin or the command line as coming from the locale LOCALE, this would only affect month and weekday names as input formats have to be specified explicitly. --from-zone=ZONE Interpret dates on stdin or the command line as coming from the time zone ZONE. -z, --zone=ZONE Convert dates printed on stdout to time zone ZONE, default: UTC. dateutils-0.4.5/src/ddiff.c000066400000000000000000000417521335042257000155370ustar00rootroot00000000000000/*** ddiff.c -- perform simple date arithmetic, date minus date * * Copyright (C) 2011-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of dateutils. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * **/ #if defined HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include "date-core-private.h" #include "dt-core-private.h" #include "dt-io.h" #include "dt-locale.h" #include "prchunk.h" #if !defined UNUSED # define UNUSED(_x) __attribute__((unused)) _x #endif /* !UNUSED */ typedef union { unsigned int flags; struct { unsigned int has_year:1; unsigned int has_mon:1; unsigned int has_week:1; unsigned int has_day:1; unsigned int has_biz:1; unsigned int has_hour:1; unsigned int has_min:1; unsigned int has_sec:1; unsigned int has_nano:1; unsigned int has_tai:1; }; } durfmt_t; const char *prog = "ddiff"; static durfmt_t determine_durfmt(const char *fmt) { durfmt_t res = {0}; dt_dtyp_t special; if (fmt == NULL) { /* decide later on */ ; } else if (UNLIKELY((special = __trans_dfmt_special(fmt)) != DT_DUNK)) { switch (special) { default: case DT_DUNK: break; case DT_YMD: res.has_year = 1; res.has_mon = 1; res.has_day = 1; break; case DT_YMCW: res.has_year = 1; res.has_mon = 1; res.has_week = 1; res.has_day = 1; break; case DT_BIZDA: res.has_year = 1; res.has_mon = 1; res.has_day = 1; res.has_biz = 1; break; case DT_DAISY: res.has_day = 1; break; case DT_BIZSI: res.has_day = 1; res.has_biz = 1; break; case DT_YWD: res.has_year = 1; res.has_week = 1; res.has_day = 1; break; case DT_YD: res.has_year = 1; res.has_day = 1; break; } /* all special types have %0H:%0M:%0S */ res.has_hour = 1; res.has_min = 1; res.has_sec = 1; } else { /* go through the fmt specs */ for (const char *fp = fmt; *fp;) { const char *fp_sav = fp; struct dt_spec_s spec = __tok_spec(fp_sav, &fp); switch (spec.spfl) { case DT_SPFL_UNK: default: /* nothing changes */ break; case DT_SPFL_N_YEAR: res.has_year = 1; break; case DT_SPFL_N_MON: case DT_SPFL_S_MON: res.has_mon = 1; break; case DT_SPFL_N_DCNT_MON: if (spec.bizda) { res.has_biz = 1; } case DT_SPFL_N_DSTD: case DT_SPFL_N_DCNT_YEAR: res.has_day = 1; break; case DT_SPFL_N_WCNT_MON: case DT_SPFL_N_WCNT_YEAR: case DT_SPFL_N_DCNT_WEEK: case DT_SPFL_S_WDAY: res.has_week = 1; break; case DT_SPFL_N_TSTD: case DT_SPFL_N_SEC: if (spec.tai) { res.has_tai = 1; } res.has_sec = 1; break; case DT_SPFL_N_HOUR: res.has_hour = 1; break; case DT_SPFL_N_MIN: res.has_min = 1; break; case DT_SPFL_N_NANO: res.has_nano = 1; break; } } } return res; } static dt_dtdurtyp_t determine_durtype(struct dt_dt_s d1, struct dt_dt_s d2, durfmt_t f) { /* the type-multiplication table looks like: * * - D T DT * D d x d * T x t x * DT d x s * * where d means a ddur type, t a tdur type and s is DT_SEXY */ if (UNLIKELY(dt_sandwich_only_t_p(d1) && dt_sandwich_only_t_p(d2))) { /* time only duration */ ; } else if (dt_sandwich_only_t_p(d1) || dt_sandwich_only_t_p(d2)) { /* isn't defined */ return (dt_dtdurtyp_t)DT_DURUNK; } else if (f.has_week && f.has_mon) { return (dt_dtdurtyp_t)DT_DURYMD; } else if (f.has_week && f.has_year) { return (dt_dtdurtyp_t)DT_DURYWD; } else if (f.has_mon) { return (dt_dtdurtyp_t)DT_DURYMD; } else if (f.has_year && f.has_day) { return (dt_dtdurtyp_t)DT_DURYD; } else if (f.has_day && f.has_biz) { return (dt_dtdurtyp_t)DT_DURBD; } else if (f.has_year) { return (dt_dtdurtyp_t)DT_DURYMD; } else if (dt_sandwich_only_d_p(d1) || dt_sandwich_only_d_p(d2)) { /* default date-only type */ return (dt_dtdurtyp_t)DT_DURD; } else if (UNLIKELY(f.has_tai)) { /* we has tais */ return (dt_dtdurtyp_t)0xffU; } /* otherwise */ return DT_DURS; } static size_t ltostr(char *restrict buf, size_t bsz, long int v, int range, unsigned int pad) { #define C(x) (char)((x) + '0') char *restrict bp = buf; const char *const ep = buf + bsz; bool negp; if (UNLIKELY((negp = v < 0))) { v = -v; } else if (!v) { *bp++ = C(0U); range--; } /* write the mantissa right to left */ for (; v && bp < ep; range--) { register unsigned int x = v % 10U; v /= 10U; *bp++ = C(x); } /* fill up with padding */ if (UNLIKELY(pad)) { static const char pads[] = " 0"; const char p = pads[2U - pad]; while (range-- > 0) { *bp++ = p; } } /* write the sign */ if (UNLIKELY(negp)) { *bp++ = '-'; } /* reverse the string */ for (char *ip = buf, *jp = bp - 1; ip < jp; ip++, jp--) { register char tmp = *ip; *ip = *jp; *jp = tmp; } #undef C return bp - buf; } static inline void dt_io_warn_dur(const char *d1, const char *d2) { error("\ duration between `%s' and `%s' is not defined", d1, d2); return; } static __attribute__((pure)) long int __strf_tot_secs(struct dt_dtdur_s dur) { /* return time portion of duration in UTC seconds */ long int s = dur.dv; if (UNLIKELY(dur.tai) && dur.durtyp == DT_DURS) { return dur.soft - dur.corr; } switch (dur.durtyp) { default: /* all the date types */ return dur.t.sdur; case DT_DURH: s *= MINS_PER_HOUR; /*@fallthrough@*/ case DT_DURM: s *= SECS_PER_MIN; /*@fallthrough@*/ case DT_DURS: break; case DT_DURNANO: s /= NANOS_PER_SEC; break; } return s; } static __attribute__((pure)) long int __strf_tot_corr(struct dt_dtdur_s dur) { if (dur.durtyp == DT_DURS && dur.tai) { return dur.corr; } /* otherwise no corrections */ return 0; } static __attribute__((pure)) int __strf_tot_days(struct dt_dtdur_s dur) { /* return date portion of DURation in days */ int d; switch (dur.d.durtyp) { case DT_DURD: case DT_DURBD: d = dur.d.dv; break; case DT_DURBIZDA: d = dur.d.bizda.bd; break; case DT_DURYMD: d = dur.d.ymd.d; break; case DT_DURYD: d = dur.d.yd.d; break; case DT_DURYMCW: d = dur.d.ymcw.w + dur.d.ymcw.c * (int)GREG_DAYS_P_WEEK; break; case DT_DURYWD: d = dur.d.ywd.w + dur.d.ywd.c * (int)GREG_DAYS_P_WEEK; break; default: d = 0; break; } return d; } static __attribute__((pure)) int __strf_tot_mon(struct dt_dtdur_s dur) { /* DUR expressed as month and days */ int m; switch (dur.d.durtyp) { case DT_DURBIZDA: m = dur.d.bizda.m + dur.d.bizda.y * (int)GREG_MONTHS_P_YEAR; break; case DT_DURYMD: m = dur.d.ymd.m + dur.d.ymd.y * (int)GREG_MONTHS_P_YEAR; break; case DT_DURYMCW: m = dur.d.ymcw.m + dur.d.ymcw.y * (int)GREG_MONTHS_P_YEAR; break; case DT_DURYD: m = dur.d.yd.y * (int)GREG_MONTHS_P_YEAR; break; case DT_DURYWD: m = dur.d.ywd.y * (int)GREG_MONTHS_P_YEAR; break; default: m = 0; break; } return m; } static __attribute__((pure)) int __strf_ym_mon(struct dt_dtdur_s dur) { return __strf_tot_mon(dur) % (int)GREG_MONTHS_P_YEAR; } static __attribute__((pure)) int __strf_tot_years(struct dt_dtdur_s dur) { return __strf_tot_mon(dur) / (int)GREG_MONTHS_P_YEAR; } static struct precalc_s { int Y; int m; int w; int d; int db; long int H; long int M; long int S; long int N; long int rS; } precalc(durfmt_t f, struct dt_dtdur_s dur) { #define MINS_PER_DAY (MINS_PER_HOUR * HOURS_PER_DAY) #define SECS_PER_WEEK (SECS_PER_DAY * GREG_DAYS_P_WEEK) #define MINS_PER_WEEK (MINS_PER_DAY * GREG_DAYS_P_WEEK) #define HOURS_PER_WEEK (HOURS_PER_DAY * GREG_DAYS_P_WEEK) struct precalc_s res = {0}; long long int us; /* date specs */ if (f.has_year) { /* just years */ res.Y = __strf_tot_years(dur); } if (f.has_year && f.has_mon) { /* years and months */ res.m = __strf_ym_mon(dur); } else if (f.has_mon) { /* just months */ res.m = __strf_tot_mon(dur); } /* the other units are easily converted as their factors are fixed. * we operate on clean seconds and attribute leap seconds only * to the S slot, so 59 seconds plus a leap second != 1 minute */ with (long long int S = __strf_tot_secs(dur), d = __strf_tot_days(dur)) { us = d * (int)SECS_PER_DAY + S; } if (f.has_week) { /* week shadows days in the hierarchy */ res.w = us / (int)SECS_PER_WEEK; us %= (int)SECS_PER_WEEK; } if (f.has_day) { res.d += us / (int)SECS_PER_DAY; us %= (int)SECS_PER_DAY; } if (f.has_hour) { res.H = us / (long int)SECS_PER_HOUR; us %= (long int)SECS_PER_HOUR; } if (f.has_min) { /* minutes and seconds */ res.M = us / (long int)SECS_PER_MIN; us %= (long int)SECS_PER_MIN; } if (f.has_sec) { res.S = us + __strf_tot_corr(dur); } /* just in case the duration iss negative jump through all * the hoops again, backwards */ if (res.w < 0 || res.d < 0 || res.H < 0 || res.M < 0 || res.S < 0) { if (0) { fixup_d: res.d = -res.d; fixup_H: res.H = -res.H; fixup_M: res.M = -res.M; fixup_S: res.S = -res.S; } else if (f.has_week) { goto fixup_d; } else if (f.has_day) { goto fixup_H; } else if (f.has_hour) { goto fixup_M; } else if (f.has_min) { goto fixup_S; } } return res; } static size_t __strfdtdur( char *restrict buf, size_t bsz, const char *fmt, struct dt_dtdur_s dur, durfmt_t f, bool only_d_p) { /* like strfdtdur() but do some calculations based on F on the way there */ static const char sexy_dflt_dur[] = "%0T"; static const char ddur_dflt_dur[] = "%d"; struct precalc_s pre; const char *fp; char *bp; if (UNLIKELY(buf == NULL || bsz == 0)) { bp = buf; goto out; } /* translate high-level format names */ if (fmt == NULL && dur.durtyp >= (dt_dtdurtyp_t)DT_NDURTYP) { fmt = sexy_dflt_dur; f.has_sec = 1U; } else if (fmt == NULL) { fmt = ddur_dflt_dur; f.has_day = 1U; } else if (only_d_p) { __trans_ddurfmt(&fmt); } else { __trans_dtdurfmt(&fmt); } /* precompute */ pre = precalc(f, dur); /* assign and go */ bp = buf; fp = fmt; if (dur.neg) { *bp++ = '-'; } for (char *const eo = buf + bsz; *fp && bp < eo;) { const char *fp_sav = fp; struct dt_spec_s spec = __tok_spec(fp_sav, &fp); if (spec.spfl == DT_SPFL_UNK) { /* must be literal then */ *bp++ = *fp_sav; } else if (UNLIKELY(spec.rom)) { continue; } /* otherwise switch over spec.spfl */ switch (spec.spfl) { case DT_SPFL_LIT_PERCENT: /* literal % */ *bp++ = '%'; break; case DT_SPFL_LIT_TAB: /* literal tab */ *bp++ = '\t'; break; case DT_SPFL_LIT_NL: /* literal \n */ *bp++ = '\n'; break; case DT_SPFL_N_DSTD: bp += ltostr(bp, eo - bp, pre.d, -1, DT_SPPAD_NONE); *bp++ = 'd'; goto bizda_suffix; case DT_SPFL_N_DCNT_MON: { int rng = 2; if (!f.has_mon && !f.has_week && f.has_year) { rng++; } bp += ltostr(bp, eo - bp, pre.d, rng, spec.pad); } bizda_suffix: if (spec.bizda) { /* don't print the b after an ordinal */ dt_bizda_param_t bprm; bprm.bs = dur.d.param; switch (bprm.ab) { case BIZDA_AFTER: *bp++ = 'b'; break; case BIZDA_BEFORE: *bp++ = 'B'; break; } } break; case DT_SPFL_N_WCNT_MON: case DT_SPFL_N_DCNT_WEEK: bp += ltostr(bp, eo - bp, pre.w, 2, spec.pad); break; case DT_SPFL_N_MON: bp += ltostr(bp, eo - bp, pre.m, 2, spec.pad); break; case DT_SPFL_N_YEAR: bp += ltostr(bp, eo - bp, pre.Y, -1, DT_SPPAD_NONE); break; /* time specs */ case DT_SPFL_N_TSTD: if (UNLIKELY(spec.tai)) { pre.S += __strf_tot_corr(dur); } bp += ltostr(bp, eo - bp, pre.S, -1, DT_SPPAD_NONE); *bp++ = 's'; break; case DT_SPFL_N_SEC: if (UNLIKELY(spec.tai)) { pre.S += __strf_tot_corr(dur); } bp += ltostr(bp, eo - bp, pre.S, 2, spec.pad); break; case DT_SPFL_N_MIN: bp += ltostr(bp, eo - bp, pre.M, 2, spec.pad); break; case DT_SPFL_N_HOUR: bp += ltostr(bp, eo - bp, pre.H, 2, spec.pad); break; default: break; } } out: if (bp < buf + bsz) { *bp = '\0'; } return bp - buf; } static int ddiff_prnt(struct dt_dtdur_s dur, const char *fmt, durfmt_t f, bool only_d_p) { /* this is mainly a better dt_strfdtdur() */ char buf[256]; size_t res = __strfdtdur(buf, sizeof(buf), fmt, dur, f, only_d_p); if (res > 0 && buf[res - 1] != '\n') { /* auto-newline */ buf[res++] = '\n'; } if (res > 0) { __io_write(buf, res, stdout); } return (res > 0) - 1; } #include "ddiff.yucc" int main(int argc, char *argv[]) { yuck_t argi[1U]; struct dt_dt_s d; const char *ofmt; const char *refinp; char **fmt; size_t nfmt; int rc = 0; durfmt_t dfmt; dt_dtdurtyp_t dtyp; zif_t fromz = NULL; if (yuck_parse(argi, argc, argv)) { rc = 1; goto out; } /* unescape sequences, maybe */ if (argi->backslash_escapes_flag) { dt_io_unescape(argi->format_arg); } if (argi->from_locale_arg) { setilocale(argi->from_locale_arg); } /* try and read the from and to time zones */ if (argi->from_zone_arg) { fromz = dt_io_zone(argi->from_zone_arg); } if (argi->base_arg) { struct dt_dt_s base = dt_strpdt(argi->base_arg, NULL, NULL); dt_set_base(base); } ofmt = argi->format_arg; fmt = argi->input_format_args; nfmt = argi->input_format_nargs; if (argi->nargs == 0 || (refinp = argi->args[0U], dt_unk_p(d = dt_io_strpdt(refinp, fmt, nfmt, fromz)) && dt_unk_p(d = dt_io_strpdt(refinp, NULL, 0U, fromz)))) { error("Error: reference DATE must be specified\n"); yuck_auto_help(argi); rc = 1; goto out; } else if (UNLIKELY(d.fix) && !argi->quiet_flag) { rc = 2; } /* try and guess the diff tgttype most suitable for user's FMT */ dfmt = determine_durfmt(ofmt); if (argi->nargs > 1) { for (size_t i = 1; i < argi->nargs; i++) { struct dt_dt_s d2; struct dt_dtdur_s dur; const char *inp = argi->args[i]; bool onlydp; d2 = dt_io_strpdt(inp, fmt, nfmt, fromz); if (dt_unk_p(d2)) { if (!argi->quiet_flag) { dt_io_warn_strpdt(inp); rc = 2; } continue; } else if (UNLIKELY(d2.fix) && !argi->quiet_flag) { rc = 2; } /* guess the diff type */ onlydp = dt_sandwich_only_d_p(d) || dt_sandwich_only_d_p(d2); if (!(dtyp = determine_durtype(d, d2, dfmt))) { if (!argi->quiet_flag) { dt_io_warn_dur(refinp, inp); rc = 2; } continue; } /* subtraction and print */ dur = dt_dtdiff(dtyp, d, d2); ddiff_prnt(dur, ofmt, dfmt, onlydp); } } else { /* read from stdin */ size_t lno = 0; void *pctx; /* no threads reading this stream */ __io_setlocking_bycaller(stdout); /* using the prchunk reader now */ if ((pctx = init_prchunk(STDIN_FILENO)) == NULL) { serror("Error: could not open stdin"); goto out; } while (prchunk_fill(pctx) >= 0) { for (char *line; prchunk_haslinep(pctx); lno++) { struct dt_dt_s d2; struct dt_dtdur_s dur; bool onlydp; (void)prchunk_getline(pctx, &line); d2 = dt_io_strpdt(line, fmt, nfmt, fromz); if (dt_unk_p(d2)) { if (!argi->quiet_flag) { dt_io_warn_strpdt(line); rc = 2; } if (argi->skip_illegal_flag) { /* empty line */ __io_write("\n", 1U, stdout); } continue; } else if (UNLIKELY(d2.fix) && !argi->quiet_flag) { rc = 2; } /* guess the diff type */ onlydp = dt_sandwich_only_d_p(d) || dt_sandwich_only_d_p(d2); if (!(dtyp = determine_durtype(d, d2, dfmt))) { if (!argi->quiet_flag) { dt_io_warn_dur(refinp, line); rc = 2; } continue; } /* perform subtraction now */ dur = dt_dtdiff(dtyp, d, d2); ddiff_prnt(dur, ofmt, dfmt, onlydp); } } /* get rid of resources */ free_prchunk(pctx); } dt_io_clear_zones(); if (argi->from_locale_arg) { setilocale(NULL); } out: yuck_free(argi); return rc; } /* ddiff.c ends here */ dateutils-0.4.5/src/ddiff.yuck000066400000000000000000000062431335042257000162640ustar00rootroot00000000000000Usage: datediff [OPTION]... DATE/TIME [DATE/TIME]... Compute duration from DATE/TIME (the reference date/time) to the other DATE/TIMEs given and print the result as duration. If the other DATE/TIMEs are omitted read them from stdin. DATE/TIME can also be one of the following specials - `now' interpreted as the current (UTC) time stamp - `time' the time part of the current (UTC) time stamp - `today' the current date (according to UTC) - `tomo[rrow]' tomorrow's date (according to UTC) - `y[ester]day' yesterday's date (according to UTC) Note: The output format of durations (specified via -f) takes all format specifiers into account, i.e. specifying %M and %S for example prints the duration in minutes and seconds, whereas specifying %S only prints the duration in seconds. See section `The refinement rule' in ddiff(1). -h, --help Print help and exit -V, --version Print version and exit -q, --quiet Suppress message about date/time and duration parser errors and fix-ups. The default is to print a warning or the fixed up value and return error code 2. Also see -S|--skip-illegal to output an empty line instead of leaving out the line altogether. -S, --skip-illegal Output empty lines as placeholder for illegal input, i.e. parser errors or date/times that cannot be subtracted. -f, --format=STRING Output format. This can either be a specifier string (similar to strftime()'s FMT) or the name of a calendar. -i, --input-format=STRING... Input format, can be used multiple times. Each date/time will be passed to the input format parsers in the order they are given, if a date/time can be read successfully with a given input format specifier string, that value will be used. -b, --base=DT For underspecified input use DT as a fallback to fill in missing fields. Also used for ambiguous format specifiers to position their range on the absolute time line. Must be a date/time in ISO8601 format. If omitted defaults to the current date/time. -e, --backslash-escapes Enable interpretation of backslash escapes in the output and input format specifier strings. --from-locale=LOCALE Interpret dates on stdin or the command line as coming from the locale LOCALE, this would only affect month and weekday names as input formats have to be specified explicitly. --from-zone=ZONE Interpret dates on stdin or the command line as coming from the time zone ZONE. dateutils-0.4.5/src/dexpr-parser.y000066400000000000000000000134061335042257000171200ustar00rootroot00000000000000/*** dexpr-parser.y -- parsing date expressions -*- c -*- * * Copyright (C) 2002-2016 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of dateutils. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***/ %pure-parser %parse-param{dexpr_t *cur} %{ #include #include #include #include "token.h" #include "date-core.h" #include "date-core-strpf.h" #include "dt-locale.h" #include "dexpr.h" #include "dexpr-parser.h" #include "dt-io.h" extern int yylex(YYSTYPE *yylval_param); extern int yyerror(dexpr_t *cur __attribute__((unused)), const char *errmsg); extern char *yytext; /* grrrrr, bug in bison */ extern int yyparse(); #define YYENABLE_NLS 0 #define YYLTYPE_IS_TRIVIAL 1 #define YYSTACK_USE_ALLOCA 1 int yyerror(dexpr_t *cur __attribute__((unused)), const char *errmsg) { fputs("dexpr-parser: ", stderr); fputs(errmsg, stderr); if (errno) { fputc(':', stderr); fputc(' ', stderr); fputs(strerror(errno), stderr); } fputc('\n', stderr); return -1; } /* static stuff */ static struct dexkv_s ckv[1]; static char *const *ckv_fmt = NULL; static size_t ckv_nfmt = 0; %} %union { dexpr_t dex; char *sval; } %expect 0 %start root %token TOK_EQ %token TOK_NE %token TOK_LT %token TOK_LE %token TOK_GT %token TOK_GE %token TOK_SPEC %token TOK_STRING %token TOK_DATETIME %token TOK_INT %token TOK_OR %token TOK_AND %token TOK_NOT %token TOK_LPAREN %token TOK_RPAREN %left TOK_OR %left TOK_AND %left TOK_NOT %% root: stmt { *cur = $$; YYACCEPT; } stmt : { memset(ckv, 0, sizeof(*ckv)); } exp { $$ = calloc(1, sizeof(struct dexpr_s)); $$->type = DEX_VAL; $$->kv[0] = *ckv; } | stmt TOK_OR stmt { $$ = calloc(1, sizeof(struct dexpr_s)); $$->type = DEX_DISJ; $$->left = $1; $$->right = $3; } | stmt TOK_AND stmt { $$ = calloc(1, sizeof(struct dexpr_s)); $$->type = DEX_CONJ; $$->left = $1; $$->right = $3; } | TOK_NOT stmt { ($$ = $2)->nega = 1; } | TOK_LPAREN stmt TOK_RPAREN { $$ = $2; } ; exp : rhs | spec TOK_LT { ckv->op = OP_LT; } rhs | spec TOK_GT { ckv->op = OP_GT; } rhs | spec TOK_LE { ckv->op = OP_LE; } rhs | spec TOK_GE { ckv->op = OP_GE; } rhs | spec TOK_EQ { ckv->op = OP_EQ; } rhs | spec TOK_NE { ckv->op = OP_NE; } rhs ; spec : | TOK_SPEC { struct dt_spec_s sp = __tok_spec($1, NULL); ckv->sp = sp; } ; rhs : TOK_DATETIME { ckv->d = dt_io_strpdt($1, ckv_fmt, ckv_nfmt, NULL); if (ckv->d.typ == DT_UNK) { /* one more try */ ckv->d = dt_strpdt($1, NULL, NULL); } ckv->sp.spfl = DT_SPFL_N_STD; } | TOK_STRING { switch (ckv->sp.spfl) { case DT_SPFL_N_YEAR: case DT_SPFL_N_MON: case DT_SPFL_N_DCNT_WEEK: case DT_SPFL_N_DCNT_MON: case DT_SPFL_N_DCNT_YEAR: case DT_SPFL_N_WCNT_MON: case DT_SPFL_N_WCNT_YEAR: ckv->s = strtol($1, NULL, 10); break; case DT_SPFL_S_WDAY: switch (ckv->sp.abbr) { case DT_SPMOD_NORM: ckv->s = strtoarri( $1, NULL, dut_abbr_wday, dut_nabbr_wday); break; case DT_SPMOD_LONG: ckv->s = strtoarri( $1, NULL, dut_long_wday, dut_nlong_wday); break; case DT_SPMOD_ABBR: { const char *pos; if ((pos = strchr( dut_abab_wday, *$1)) != NULL) { ckv->s = pos - dut_abab_wday; break; } } case DT_SPMOD_ILL: default: ckv->s = -1; break; } break; case DT_SPFL_S_MON: switch (ckv->sp.abbr) { case DT_SPMOD_NORM: ckv->s = strtoarri( $1, NULL, dut_abbr_mon, dut_nabbr_mon); break; case DT_SPMOD_LONG: ckv->s = strtoarri( $1, NULL, dut_long_mon, dut_nlong_mon); break; case DT_SPMOD_ABBR: { const char *pos; if ((pos = strchr( dut_abab_mon, *$1)) != NULL) { ckv->s = pos - dut_abab_mon; break; } } case DT_SPMOD_ILL: default: ckv->s = -1; break; } break; default: break; } } | TOK_INT { switch (ckv->sp.spfl) { case DT_SPFL_N_YEAR: case DT_SPFL_N_MON: case DT_SPFL_N_DCNT_WEEK: case DT_SPFL_N_DCNT_MON: case DT_SPFL_N_DCNT_YEAR: case DT_SPFL_N_WCNT_MON: case DT_SPFL_N_WCNT_YEAR: ckv->s = strtol($1, NULL, 10); break; default: /* the rest can hardly have ints as inputs */ YYERROR; } } ; %% /* dexpr-parser.y ends here */ dateutils-0.4.5/src/dexpr-scanner.l000066400000000000000000000072511335042257000172410ustar00rootroot00000000000000/*** dexpr.l -- date/time expressions for dateutils -*- C -*- * * Copyright (C) 2002-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of dateutils. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***/ %{ #include "dexpr.h" #include "dexpr-parser.h" /* grrrrr, bug in bison */ extern int yyparse(); /* turn off tedious warnings */ #if defined __INTEL_COMPILER # pragma warning (disable:593) # pragma warning (disable:869) # pragma warning (disable:1419) # pragma warning (disable:2259) #elif defined __GNUC__ # pragma GCC diagnostic ignored "-Wswitch-default" # pragma GCC diagnostic ignored "-Wsign-compare" # pragma GCC diagnostic ignored "-Wunused-parameter" #endif /* __GNUC__ || __INTEL_COMPILER */ %} %option noyywrap %option nounput %option noinput %option warn %option bison-bridge %option pointer %option nodebug %{ #define RETURN_TOKEN(_x) \ do { \ return _x; \ } while (0) %} ws [ \t\v\n\f] string \"(\\.|[^\\\"])*\"|'(\\.|[^\\\'])*' /* only canonical dates are allowed */ int [0-9]+ %% "="=? { RETURN_TOKEN(TOK_EQ); } "!=" { RETURN_TOKEN(TOK_NE); } "<" { RETURN_TOKEN(TOK_LT); } "<=" { RETURN_TOKEN(TOK_LE); } ">" { RETURN_TOKEN(TOK_GT); } ">=" { RETURN_TOKEN(TOK_GE); } "||" { RETURN_TOKEN(TOK_OR); } "&&" { RETURN_TOKEN(TOK_AND); } "!" { RETURN_TOKEN(TOK_NOT); } "(" { RETURN_TOKEN(TOK_LPAREN); } ")" { RETURN_TOKEN(TOK_RPAREN); } "%"[_a-zA-Z]* { yylval->sval = yytext; RETURN_TOKEN(TOK_SPEC); } {string} { /* strip quotes */ yytext[yyleng - 1] = '\0'; yylval->sval = yytext + 1; RETURN_TOKEN(TOK_STRING); } {int} { yylval->sval = yytext; RETURN_TOKEN(TOK_INT); } [^\v\n\f()!&|<>= ][^\v\n\f()!&|<>=]* { /* return for parsing with our strpdt reader */ yylval->sval = yytext; RETURN_TOKEN(TOK_DATETIME); } {ws} { /* ignore whitespace */ } . { /* ignore */ } %% int dexpr_parse(dexpr_t *root, const char *s, size_t l) { YY_BUFFER_STATE buf; char *scan; int res; /* hack to avoid string dup'ing, we assume, that l can take * at least 2 more bytes */ if ((scan = malloc(l + 2)) == NULL) { return -1; } memcpy(scan, s, l); scan[l++] = '\0'; scan[l++] = '\0'; buf = yy_scan_buffer(scan, l); /* parse them */ res = yyparse(root); yy_delete_buffer(buf); return (res == 0) - 1; } /* dexpr.l ends here */ dateutils-0.4.5/src/dexpr.c000066400000000000000000000303031335042257000155730ustar00rootroot00000000000000#if defined HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include #include #include #include #include "strops.h" #include "dt-locale.h" #include "dexpr.h" #include "dexpr-parser.h" #if !defined STANDALONE # if defined __INTEL_COMPILER # pragma warning (disable:2259) # endif /* __INTEL_COMPILER */ # include "dexpr-parser.c" # if defined __INTEL_COMPILER # pragma warning (default:2259) # endif /* __INTEL_COMPILER */ # if defined __INTEL_COMPILER # pragma warning (disable:2557) # endif /* __INTEL_COMPILER */ # include "dexpr-scanner.c" # if defined __INTEL_COMPILER # pragma warning (default:2557) # endif /* __INTEL_COMPILER */ #endif /* !STANDALONE */ static void free_dexpr(dexpr_t root) { /* recursive free :( */ switch (root->type) { case DEX_CONJ: case DEX_DISJ: if (root->left != NULL) { free_dexpr(root->left); free(root->left); } if (root->right != NULL) { free_dexpr(root->right); free(root->right); } break; case DEX_UNK: case DEX_VAL: default: break; } return; } static __attribute__((unused)) void __pr_val(struct dexkv_s *kv) { switch (kv->sp.spfl) { case DT_SPFL_N_DCNT_MON: fputs("%d ", stdout); break; case DT_SPFL_N_MON: case DT_SPFL_S_MON: fputs("%b ", stdout); break; case DT_SPFL_N_YEAR: fputs("%Y ", stdout); break; case DT_SPFL_N_DCNT_WEEK: case DT_SPFL_S_WDAY: fputs("%a ", stdout); break; case DT_SPFL_N_WCNT_MON: fputs("%c ", stdout); break; case DT_SPFL_N_DCNT_YEAR: fputs("%D ", stdout); break; case DT_SPFL_N_WCNT_YEAR: fputs("%C ", stdout); break; default: break; } switch (kv->op) { case OP_LT: fputs("< ", stdout); break; case OP_LE: fputs("<= ", stdout); break; case OP_GT: fputs("> ", stdout); break; case OP_GE: fputs(">= ", stdout); break; case OP_NE: fputs("!= ", stdout); break; case OP_EQ: default: fputs("== ", stdout); break; } switch (kv->sp.spfl) { case DT_SPFL_N_STD: { char buf[32]; dt_strfdt(buf, sizeof(buf), NULL, kv->d); fputs(buf, stdout); break; } case DT_SPFL_N_DCNT_MON: fprintf(stdout, "%02d", kv->s); break; case DT_SPFL_N_MON: case DT_SPFL_S_MON: if (kv->s >= 0 && kv->s <= 12) { fputs(dut_abbr_mon[kv->s], stdout); } break; case DT_SPFL_N_YEAR: fprintf(stdout, "%04d", kv->s); break; case DT_SPFL_N_DCNT_WEEK: case DT_SPFL_S_WDAY: if (kv->s >= 0 && kv->s <= 7) { fputs(dut_abbr_wday[kv->s], stdout); } break; case DT_SPFL_N_WCNT_MON: case DT_SPFL_N_WCNT_YEAR: fprintf(stdout, "%02d", kv->s); break; case DT_SPFL_N_DCNT_YEAR: fprintf(stdout, "%03d", kv->s); break; default: break; } return; } static __attribute__((unused)) void __pr(dexpr_t root, size_t ind) { switch (root->type) { case DEX_VAL: for (size_t i = 0; i < ind; i++) { fputc(' ', stdout); } if (root->nega) { fputs("!(", stdout); } __pr_val(root->kv); if (root->nega) { fputs(")\n", stdout); } else { fputc('\n', stdout); } break; case DEX_CONJ: for (size_t i = 0; i < ind; i++) { fputc(' ', stdout); } if (!root->nega) { fputs("AND\n", stdout); } else { fputs("NAND\n", stdout); } __pr(root->left, ind + 2); __pr(root->right, ind + 2); break; case DEX_DISJ: for (size_t i = 0; i < ind; i++) { fputc(' ', stdout); } if (!root->nega) { fputs("OR\n", stdout); } else { fputs("NOR\n", stdout); } __pr(root->left, ind + 2); __pr(root->right, ind + 2); break; case DEX_UNK: default: for (size_t i = 0; i < ind; i++) { fputc(' ', stdout); } if (root->left != NULL) { fputs("ROOT\n", stderr); __pr(root->left, ind + 2); break; } break; } return; } static __attribute__((unused)) void __pr_infix(dexpr_t root) { if (root->type == DEX_VAL) { __pr_val(root->kv); return; } __pr_infix(root->left); switch (root->type) { case DEX_CONJ: fputs(" && ", stdout); break; case DEX_DISJ: fputs(" || ", stdout); break; case DEX_VAL: case DEX_UNK: default: /* shouldn't happen :O */ fputs(" bollocks ", stdout); break; } __pr_infix(root->right); /* just ascend */ return; } static dexpr_t make_dexpr(dex_type_t type) { dexpr_t res; if ((res = calloc(1, sizeof(*res))) != NULL) { res->type = type; } return res; } static dexpr_t dexpr_copy(const_dexpr_t src) { dexpr_t res; if ((res = calloc(1, sizeof(*res))) == NULL) { return NULL; } /* otherwise start by (shallow) copying things */ memcpy(res, src, sizeof(*res)); /* deep copy anyone? */ switch (src->type) { case DEX_CONJ: case DEX_DISJ: res->left = dexpr_copy(src->left); res->right = dexpr_copy(src->right); break; case DEX_VAL: case DEX_UNK: default: break; } return res; } static dexpr_t dexpr_copy_j(dexpr_t src) { /* copy SRC, but only if it's a junction (disjunction or conjunction) */ if (src->type == DEX_VAL) { return (dexpr_t)src; } return dexpr_copy(src); } static void __dnf(dexpr_t root) { /* recursive __dnf'er */ switch (root->type) { case DEX_CONJ: { /* check if one of the children is a disjunction */ dex_type_t rlt = root->left->type; dex_type_t rrt = root->right->type; if (rlt == DEX_DISJ && rrt == DEX_DISJ) { /* complexestest case * (a|b)&(c|d) -> (a&c)|(a&d)|(b&c)|(b&d) */ dexpr_t a; dexpr_t b; dexpr_t c; dexpr_t d; /* get the new idea of b and c */ a = root->left->left; b = root->left->right; c = root->right->left; d = root->right->right; /* now reuse what's possible */ root->type = DEX_DISJ; root->left->type = DEX_CONJ; #if 0 /* silly assignment, a comes from left->left */ root->left->left = a; #endif /* 0 */ root->left->right = c; root->right->type = DEX_DISJ; root->right->left = make_dexpr(DEX_CONJ); root->right->left->left = dexpr_copy_j(a); root->right->left->right = d; root->right->right = make_dexpr(DEX_DISJ); root->right->right->left = make_dexpr(DEX_CONJ); root->right->right->left->left = b; root->right->right->left->right = dexpr_copy_j(c); /* right side, finalise the right branches with CONJ */ root->right->right->right = make_dexpr(DEX_CONJ); root->right->right->right->left = dexpr_copy_j(b); root->right->right->right->right = dexpr_copy_j(d); } else if (rlt == DEX_DISJ || rrt == DEX_DISJ) { /* ok'ish case * a&(b|c) -> a&b|a&c * the other case gets normalised: (a|b)&c -> c&(a|b) */ dexpr_t a; dexpr_t b; dexpr_t c; /* put the non-DISJ case left */ if ((a = root->left)->type == DEX_DISJ) { a = root->right; root->right = root->left; } /* get the new idea of b and c */ b = root->right->left; c = root->right->right; /* turn into disjoint */ root->type = DEX_DISJ; /* inflate left branch */ root->left = make_dexpr(DEX_CONJ); root->left->left = a; root->left->right = b; /* rearrange this node now, reuse the right disjoint */ root->right->type = DEX_CONJ; root->right->left = a; root->right->right = c; } /* fallthrough! */ } case DEX_DISJ: /* nothing to be done other than a quick descent */ __dnf(root->left); __dnf(root->right); /* upon ascent fixup double OR's */ if (root->left->type == DEX_DISJ && root->right->type == DEX_DISJ) { /* | | * / \ / \ * | | ~> a | * / \ / \ / \ * a b c d b | * / \ * c d */ dexpr_t i = root->left; dexpr_t j = root->right; dexpr_t a = i->left; dexpr_t b = i->right; dexpr_t c = j->left; root->left = a; root->right = i; i->left = b; i->right = j; j->left = c; } else if (root->left->type == DEX_DISJ) { /* | | * / \ / \ * | c ~> a | * / \ / \ * a b b c */ dexpr_t i = root->left; dexpr_t c = root->right; dexpr_t a = i->left; dexpr_t b = i->right; root->left = a; root->right = i; i->left = b; i->right = c; } break; case DEX_VAL: case DEX_UNK: default: /* can't do anything to get the DNF going */ break; } return; } static void __nega_kv(struct dexkv_s *kv) { /* assume the parent dexpr has the nega flag set, negate KV */ kv->op = ~kv->op; return; } static void __denega(dexpr_t root) { dexpr_t left; dexpr_t right; if (root->nega) { /* negate */ root->nega = 0; switch (root->type) { case DEX_CONJ: /* !(a&b) -> !a | !b */ root->type = DEX_DISJ; break; case DEX_DISJ: /* !(a|b) -> !a & !b */ root->type = DEX_DISJ; break; case DEX_VAL: __nega_kv(root->kv); /* fallthrough */ case DEX_UNK: default: return; } if ((left = root->left) != NULL) { left->nega = ~left->nega; } if ((right = root->right) != NULL) { right->nega = ~right->nega; } } else { switch (root->type) { case DEX_CONJ: case DEX_DISJ: left = root->left; right = root->right; break; case DEX_VAL: case DEX_UNK: default: return; } } /* descend */ if (left != NULL) { __denega(left); } if (right != NULL) { __denega(right); } return; } static void dexpr_simplify(dexpr_t root) { __denega(root); __dnf(root); return; } static int __cmp(struct dt_dt_s stream, struct dt_dt_s cell) { /* special promoting/demoting version of dt_dtcmp() * if CELL is d-only or t-only, demote STREAM */ if (dt_sandwich_only_d_p(cell)) { return dt_dcmp(stream.d, cell.d); } else if (dt_sandwich_only_t_p(cell)) { return dt_tcmp(stream.t, cell.t); } return dt_dtcmp(stream, cell); } static bool dexkv_matches_p(const_dexkv_t dkv, struct dt_dt_s d) { signed int cmp; bool res; if (dkv->sp.spfl == DT_SPFL_N_STD) { if ((cmp = __cmp(d, dkv->d)) == -2) { return false; } switch (dkv->op) { case OP_UNK: case OP_EQ: res = cmp == 0; break; case OP_LT: res = cmp < 0; break; case OP_LE: res = cmp <= 0; break; case OP_GT: res = cmp > 0; break; case OP_GE: res = cmp >= 0; break; case OP_NE: res = cmp != 0; break; case OP_TRUE: res = true; break; default: res = false; break; } return res; } /* otherwise it's stuff that uses the S slot */ switch (dkv->sp.spfl) { case DT_SPFL_N_YEAR: cmp = dt_get_year(d.d); break; case DT_SPFL_N_MON: case DT_SPFL_S_MON: cmp = dt_get_mon(d.d); break; case DT_SPFL_N_DCNT_MON: cmp = dt_get_mday(d.d); break; case DT_SPFL_N_DCNT_WEEK: case DT_SPFL_S_WDAY: cmp = dt_get_wday(d.d); break; case DT_SPFL_N_WCNT_MON: /* exotic function, needs extern'ing */ cmp = dt_get_wcnt_mon(d.d); break; case DT_SPFL_N_DCNT_YEAR: cmp = dt_get_yday(d.d); break; case DT_SPFL_N_WCNT_YEAR: /* %C/%W week count */ cmp = dt_get_wcnt_year(d.d, dkv->sp.wk_cnt); break; case DT_SPFL_N_STD: default: return false; } /* now do the actual comparison */ switch (dkv->op) { case OP_EQ: res = dkv->s == cmp; break; case OP_LT: res = dkv->s < cmp; break; case OP_LE: res = dkv->s <= cmp; break; case OP_GT: res = dkv->s > cmp; break; case OP_GE: res = dkv->s >= cmp; break; case OP_NE: res = dkv->s != cmp; break; case OP_TRUE: res = true; break; default: case OP_UNK: res = false; break; } return res; } static bool __conj_matches_p(const_dexpr_t dex, struct dt_dt_s d) { const_dexpr_t a; for (a = dex; a->type == DEX_CONJ; a = a->right) { if (!dexkv_matches_p(a->left->kv, d)) { return false; } } /* rightmost cell might be a DEX_VAL */ return dexkv_matches_p(a->kv, d); } static bool __disj_matches_p(const_dexpr_t dex, struct dt_dt_s d) { const_dexpr_t o; for (o = dex; o->type == DEX_DISJ; o = o->right) { if (__conj_matches_p(o->left, d)) { return true; } } /* rightmost cell may be a DEX_VAL */ return __conj_matches_p(o, d); } static __attribute__((unused)) bool dexpr_matches_p(const_dexpr_t dex, struct dt_dt_s d) { return __disj_matches_p(dex, d); } #if defined STANDALONE const char *prog = "dexpr"; int main(int argc, char *argv[]) { dexpr_t root; for (int i = 1; i < argc; i++) { root = NULL; dexpr_parse(&root, argv[i], strlen(argv[i])); __pr(root, 0); fputc('\n', stdout); dexpr_simplify(root); __pr(root, 0); fputc('\n', stdout); /* also print an infix line */ __pr_infix(root); fputc('\n', stdout); free_dexpr(root); } return 0; } #endif /* STANDALONE */ /* dexpr.c ends here */ dateutils-0.4.5/src/dexpr.h000066400000000000000000000014751335042257000156100ustar00rootroot00000000000000/*** dexpr.h -- helper for date expressions */ #if !defined INCLUDED_dexpr_h_ #define INCLUDED_dexpr_h_ #include "dt-core.h" #include "token.h" typedef struct dexpr_s *dexpr_t; typedef const struct dexpr_s *const_dexpr_t; typedef struct dexkv_s *dexkv_t; typedef const struct dexkv_s *const_dexkv_t; typedef enum { DEX_UNK, DEX_VAL, DEX_CONJ, /* must be last as other types will be considered inferior */ DEX_DISJ, } dex_type_t; struct dexkv_s { struct dt_spec_s sp; oper_t op:3; union { struct dt_dt_s d; signed int s; }; }; struct dexpr_s { dex_type_t type:31; unsigned int nega:1; dexpr_t left; union { struct dexkv_s kv[1]; struct { dexpr_t right; dexpr_t up; }; }; }; /* parser routine */ extern int dexpr_parse(dexpr_t *root, const char *s, size_t l); #endif /* INCLUDED_dexpr_h_ */ dateutils-0.4.5/src/dgrep.c000066400000000000000000000143461335042257000155630ustar00rootroot00000000000000/*** dgrep.c -- grep for lines with dates * * Copyright (C) 2011-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of dateutils. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * **/ #if defined HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include "dt-core.h" #include "dt-core-tz-glue.h" #include "dt-io.h" #include "dexpr.h" #include "dt-locale.h" #include "prchunk.h" const char *prog = "dgrep"; /* dexpr subsystem */ #include "dexpr.c" struct prln_ctx_s { struct grep_atom_soa_s *ndl; dexpr_t root; zif_t fromz; zif_t z; unsigned int only_matching_p:1U; unsigned int invert_match_p:1U; }; static void proc_line(struct prln_ctx_s ctx, char *line, size_t llen) { char *osp = NULL; char *oep = NULL; /* check if line matches, * there's currently no way to specify NEEDLE */ for (char *lp = line, *const zp = line + llen, *sp, *ep; /*no check*/; lp = ep, osp = sp, oep = ep) { struct dt_dt_s d = dt_io_find_strpdt2( lp, zp - lp, ctx.ndl, &sp, &ep, ctx.fromz); bool unkp = dt_unk_p(d); if (unkp) { /* just plain nothing */ break; } else if (ctx.z != NULL) { /* promote to zone ctx.z */ d = dtz_enrichz(d, ctx.z); } /* otherwise */ if (dexpr_matches_p(ctx.root, d)) { if (ctx.invert_match_p) { /* nothing must match */ return; } else if (!ctx.only_matching_p) { sp = line; ep = line + llen; } /* make sure we finish the line */ *ep++ = '\n'; __io_write(sp, ep - sp, stdout); return; } } if (ctx.invert_match_p) { /* no match but invert_match select, print line */ if (!ctx.only_matching_p) { osp = line; oep = line + llen; } else if (osp == NULL || oep == NULL) { /* no date in line and only-matching is active * bugger off */ return; } /* finish the line and bugger off */ *oep++ = '\n'; __io_write(osp, oep - osp, stdout); } return; } #include "dgrep.yucc" int main(int argc, char *argv[]) { yuck_t argi[1U]; char **fmt; size_t nfmt; dexpr_t root; oper_t o = OP_UNK; int res = 0; if (yuck_parse(argi, argc, argv)) { res = 1; goto out; } /* init and unescape sequences, maybe */ ckv_fmt = fmt = argi->input_format_args; ckv_nfmt = nfmt = argi->input_format_nargs; if (argi->backslash_escapes_flag) { for (size_t i = 0; i < nfmt; i++) { dt_io_unescape(fmt[i]); } } if (argi->base_arg) { struct dt_dt_s base = dt_strpdt(argi->base_arg, NULL, NULL); dt_set_base(base); } if (argi->eq_flag) { o = OP_EQ; } else if (argi->ne_flag) { o = OP_NE; } else if (argi->lt_flag || argi->ot_flag) { o = OP_LT; } else if (argi->le_flag) { o = OP_LE; } else if (argi->gt_flag || argi->nt_flag) { o = OP_GT; } else if (argi->ge_flag) { o = OP_GE; } /* parse the expression */ if (argi->nargs == 0U || dexpr_parse(&root, argi->args[0U], strlen(argi->args[0U])) < 0) { res = 1; error("Error: need an expression to grep"); goto out; } /* fixup o, default is OP_EQ */ if (o != OP_UNK && root->type != DEX_VAL) { res = 1; error("\ long opt operators (--lt, --gt, ...) cannot be used in conjunction \n\ with complex expressions"); goto out; } else if (o != OP_UNK) { /* fiddle with the operator in the expression */ root->kv->op = o; } if (argi->from_locale_arg) { setilocale(argi->from_locale_arg); } /* otherwise bring dexpr to normal form */ dexpr_simplify(root); /* beef */ { /* read from stdin */ size_t lno = 0; struct grep_atom_s __nstk[16], *needle = __nstk; size_t nneedle = countof(__nstk); struct grep_atom_soa_s ndlsoa; void *pctx; struct prln_ctx_s prln = { .ndl = &ndlsoa, .root = root, .fromz = dt_io_zone(argi->from_zone_arg), .z = dt_io_zone(argi->zone_arg), .only_matching_p = argi->only_matching_flag, .invert_match_p = argi->invert_match_flag, }; /* no threads reading this stream */ __io_setlocking_bycaller(stdout); /* lest we overflow the stack */ if (nfmt >= nneedle) { /* round to the nearest 8-multiple */ nneedle = (nfmt | 7) + 1; needle = calloc(nneedle, sizeof(*needle)); } /* and now build the needle */ ndlsoa = build_needle(needle, nneedle, fmt, nfmt); /* using the prchunk reader now */ if ((pctx = init_prchunk(STDIN_FILENO)) == NULL) { serror("Error: could not open stdin"); goto ndl_free; } while (prchunk_fill(pctx) >= 0) { for (char *line; prchunk_haslinep(pctx); lno++) { size_t llen = prchunk_getline(pctx, &line); proc_line(prln, line, llen); } } /* get rid of resources */ free_prchunk(pctx); ndl_free: if (needle != __nstk) { free(needle); } } /* resource freeing */ free_dexpr(root); dt_io_clear_zones(); if (argi->from_locale_arg) { setilocale(NULL); } out: yuck_free(argi); return res; } /* dgrep.c ends here */ dateutils-0.4.5/src/dgrep.yuck000066400000000000000000000075031335042257000163110ustar00rootroot00000000000000Usage: dategrep [OPTION]... EXPRESSION Grep standard input for lines that match EXPRESSION. EXPRESSION may be date/times prefixed with an operator `<', `<=', `=', `>=', `>', `!=', `<>' (if omitted defaults to `='), which will match lines with date/times which are older, older-equal, equal, newer-equal, newer, or not equal respectively. EXPRESSION may also be format specifiers infixed by above operators and suffixed by a value (e.g. `%a="Wed"') which matches lines whose %a representation (weekday name abbreviated) is "Wed". EXPRESSION may be statements as described above concatenated through `&&' (for conjunction) or `||' (disjunction), both of which may be parenthesised as per usual to change precedence (`&&' goes over `||'). If multiple date/times occur on the same line and any one of them fulfills the criteria then the line is considered a match and will be output. -h, --help Print help and exit -V, --version Print version and exit -q, --quiet Suppress message about date/time and duration parser errors. -i, --input-format=STRING... Input format, can be used multiple times. Each date/time will be passed to the input format parsers in the order they are given, if a date/time can be read successfully with a given input format specifier string, that value will be used. -b, --base=DT For underspecified input use DT as a fallback to fill in missing fields. Also used for ambiguous format specifiers to position their range on the absolute time line. Must be a date/time in ISO8601 format. If omitted defaults to the current date/time. -e, --backslash-escapes Enable interpretation of backslash escapes in the output and input format specifier strings. -o, --only-matching Show only the part of a line matching DATE. -v, --invert-match Select non-matching lines. --from-locale=LOCALE Interpret dates on stdin or the command line as coming from the locale LOCALE, this would only affect month and weekday names as input formats have to be specified explicitly. --from-zone=ZONE Consider date/times on stdin as coming from the zone ZONE, default: UTC. -z, --zone=ZONE Consider date/times in EXPRESSION as coming from the zone ZONE, default: UTC. Note: Operations can be specified by options (--eq, --gt, ...) as well. This serves solely as a means of convenience, e.g. the dtest tool has a similar syntax. --eq Lines match when date/times are equal to EXPRESSION. --ne Lines match when date/times are not the same as EXPRESSION. --gt Lines match when date/times are newer than EXPRESSION. --lt Lines match when date/times are older than EXPRESSION. --ge Lines match when date/times are newer than or equal EXPRESSION. --le Lines match when date/times are older than or equal EXPRESSION. --nt Lines match when date/times are newer than or equal EXPRESSION. --ot Lines match when date/times are older than or equal EXPRESSION. dateutils-0.4.5/src/dround.c000066400000000000000000000452431335042257000157550ustar00rootroot00000000000000/*** dround.c -- perform simple date arithmetic, round to duration * * Copyright (C) 2012-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of dateutils. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * **/ #if defined HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include "dt-core.h" #include "dt-io.h" #include "dt-core-tz-glue.h" #include "dt-locale.h" #include "prchunk.h" /* parsers and formatters */ #include "date-core-strpf.h" #include "date-core-private.h" #if !defined assert # define assert(x) #endif /* !assert */ const char *prog = "dround"; static struct dt_t_s tround_tdur_cocl(struct dt_t_s t, struct dt_dtdur_s dur, bool nextp) { /* this will return the rounded to DUR time of T and, to encode carry * (which can only take values 0 or 1), we will use t's neg bit */ unsigned int tunp; signed int sdur; bool downp = false; /* we won't have carries, ever */ t.carry = 0; /* get directions, no dur is a no-op */ if (UNLIKELY(!(sdur = dur.dv))) { /* IPO/LTO hack */ goto out; } else if (sdur < 0) { downp = true; sdur = -sdur; } else if (dur.neg) { downp = true; } switch (dur.durtyp) { case DT_DURH: sdur *= MINS_PER_HOUR; /*@fallthrough@*/ case DT_DURM: sdur *= SECS_PER_MIN; /*@fallthrough@*/ case DT_DURS: /* only accept values whose remainder is 0 */ if (LIKELY(!(SECS_PER_DAY % (unsigned int)sdur))) { break; } /*@fallthrough@*/ default: /* IPO/LTO hack */ goto out; } /* unpack t */ tunp = (t.hms.h * MINS_PER_HOUR + t.hms.m) * SECS_PER_MIN + t.hms.s; with (unsigned int diff = tunp % (unsigned int)sdur) { if (!diff && !nextp) { /* do nothing, i.e. really nothing, * in particular, don't set the slots again in the * assign section * this is not some obscure optimisation but to * support special notations like, military midnight * or leap seconds */ goto out; } else if (!downp) { tunp += sdur - diff; } else if (!diff/* && downp && nextp*/) { tunp -= sdur; } else { tunp -= diff; } } /* assign */ t.hms.ns = 0; t.hms.s = tunp % SECS_PER_MIN; tunp /= SECS_PER_MIN; t.hms.m = tunp % MINS_PER_HOUR; tunp /= MINS_PER_HOUR; t.hms.h = tunp % HOURS_PER_DAY; out: return t; } static struct dt_t_s tround_tdur(struct dt_t_s t, struct dt_dtdur_s dur, bool nextp) { /* this will return the rounded to DUR time of T and, to encode carry * (which can only take values 0 or 1), we will use t's neg bit */ bool downp = false; signed int dv; /* initialise carry */ t.carry = 0; /* get directions */ if ((dv = dur.dv) < 0) { downp = true; dv = -dv; } else if (dur.neg) { downp = true; } switch (dur.durtyp) { case DT_DURH: if ((!downp && t.hms.h < dv) || (downp && t.hms.h > dv)) { /* no carry adjustments */ t.hms.h = dv; } else if (t.hms.h == dv && !nextp) { /* we're on the hour in question */ t.hms.h = dv; } else if (!downp) { t.hms.h = dv; hour_oflo: t.carry = 1; } else { t.hms.h = dv; hour_uflo: t.carry = -1; } break; case DT_DURM: if ((!downp && t.hms.m < dv) || (downp && t.hms.m > dv)) { /* no carry adjustments */ t.hms.m = dv; } else if (t.hms.m == dv && !nextp) { /* we're on the hour in question */ t.hms.m = dv; } else if (!downp) { t.hms.m = dv; min_oflo: if (UNLIKELY(++t.hms.h >= HOURS_PER_DAY)) { t.hms.h = 0; goto hour_oflo; } } else { t.hms.m = dv; min_uflo: if (UNLIKELY(!t.hms.h--)) { t.hms.h = HOURS_PER_DAY - 1; goto hour_uflo; } } break; case DT_DURS: if ((!downp && t.hms.s < dv) || (downp && t.hms.s > dv)) { /* no carry adjustments */ t.hms.s = dv; } else if (t.hms.s == dv && !nextp) { /* we're on the hour in question */ t.hms.s = dv; } else if (!downp) { t.hms.s = dv; if (UNLIKELY(++t.hms.m >= MINS_PER_HOUR)) { t.hms.m = 0; goto min_oflo; } } else { t.hms.s = dv; if (UNLIKELY(!t.hms.m--)) { t.hms.m = MINS_PER_HOUR - 1; goto min_uflo; } } break; default: break; } return t; } static struct dt_d_s dround_ddur(struct dt_d_s d, struct dt_ddur_s dur, bool nextp) { switch (dur.durtyp) { unsigned int tgt; bool forw; case DT_DURD: if (dur.dv > 0) { tgt = dur.dv; forw = true; } else if (dur.dv < 0) { tgt = -dur.dv; forw = false; } else { /* user is an idiot */ break; } switch (d.typ) { unsigned int mdays; case DT_YMD: if ((forw && d.ymd.d < tgt) || (!forw && d.ymd.d > tgt)) { /* no month or year adjustment */ ; } else if (d.ymd.d == tgt && !nextp) { /* we're ON the date already and no * next/prev date is requested */ ; } else if (forw) { if (LIKELY(d.ymd.m < GREG_MONTHS_P_YEAR)) { d.ymd.m++; } else { d.ymd.m = 1; d.ymd.y++; } } else { if (UNLIKELY(--d.ymd.m < 1)) { d.ymd.m = GREG_MONTHS_P_YEAR; d.ymd.y--; } } /* get ultimo */ mdays = __get_mdays(d.ymd.y, d.ymd.m); if (UNLIKELY(tgt > mdays)) { tgt = mdays; } /* final assignment */ d.ymd.d = tgt; break; default: break; } break; case DT_DURBD: /* bizsis only work on bizsidurs atm */ if (dur.dv > 0) { tgt = dur.dv; forw = true; } else if (dur.dv < 0) { tgt = -dur.dv; forw = false; } else { /* user is an idiot */ break; } switch (d.typ) { unsigned int bdays; case DT_BIZDA: if ((forw && d.bizda.bd < tgt) || (!forw && d.bizda.bd > tgt)) { /* no month or year adjustment */ ; } else if (d.bizda.bd == tgt && !nextp) { /* we're ON the date already and no * next/prev date is requested */ ; } else if (forw) { if (LIKELY(d.bizda.m < GREG_MONTHS_P_YEAR)) { d.bizda.m++; } else { d.bizda.m = 1; d.bizda.y++; } } else { if (UNLIKELY(--d.bizda.m < 1)) { d.bizda.m = GREG_MONTHS_P_YEAR; d.bizda.y--; } } /* get ultimo */ bdays = __get_bdays(d.bizda.y, d.bizda.m); if (UNLIKELY(tgt > bdays)) { tgt = bdays; } /* final assignment */ d.bizda.bd = tgt; break; default: break; } break; case DT_DURYMD: switch (d.typ) { unsigned int mdays; case DT_YMD: tgt = dur.ymd.m; forw = !dt_dur_neg_p(dur); if ((forw && d.ymd.m < tgt) || (!forw && d.ymd.m > tgt)) { /* no year adjustment */ ; } else if (d.ymd.m == tgt && !nextp) { /* we're IN the month already and no * next/prev date is requested */ ; } else if (forw) { /* years don't wrap around */ d.ymd.y++; } else { /* years don't wrap around */ d.ymd.y--; } /* final assignment */ d.ymd.m = tgt; /* fixup ultimo mismatches */ mdays = __get_mdays(d.ymd.y, d.ymd.m); if (UNLIKELY(d.ymd.d > mdays)) { d.ymd.d = mdays; } break; default: break; } break; case DT_DURYMCW: { struct dt_d_s tmp; unsigned int wday; signed int diff; forw = !dt_dur_neg_p(dur); tgt = dur.ymcw.w; tmp = dt_dconv(DT_DAISY, d); wday = dt_get_wday(tmp); diff = (signed)tgt - (signed)wday; if ((forw && wday < tgt) || (!forw && wday > tgt)) { /* nothing to do */ ; } else if (wday == tgt && !nextp) { /* we're on WDAY already, do fuckall */ ; } else if (forw) { /* week wrap */ diff += 7; } else { /* week wrap */ diff -= 7; } /* final assignment */ tmp.daisy += diff; d = dt_dconv(d.typ, tmp); break; } case DT_DURWK: if (dur.dv > 0) { tgt = dur.dv; forw = true; } else if (dur.dv < 0) { tgt = -dur.dv; forw = false; } else { /* user is an idiot */ break; } switch (d.typ) { unsigned int nw; case DT_YWD: if ((forw && d.ywd.c < tgt) || (!forw && d.ywd.c > tgt)) { /* no year adjustment */ ; } else if (d.ywd.c == tgt && !nextp) { /* we're IN the week already and no * next/prev date is requested */ ; } else if (forw) { /* years don't wrap around */ d.ywd.y++; } else { /* years don't wrap around */ d.ywd.y--; } /* final assignment */ d.ywd.c = tgt; /* fixup ultimo mismatches */ nw = __get_isowk(d.ywd.y); if (UNLIKELY(d.ywd.c > nw)) { d.ywd.c = nw; } break; default: break; } break; default: break; } return d; } static dt_sexy_t sxround_dur_cocl(dt_sexy_t t, struct dt_dtdur_s dur, bool nextp) { /* this will return the rounded to DUR time of T and, to encode carry * (which can only take values 0 or 1), we will use t's neg bit */ dt_ssexy_t sdur; bool downp = false; /* get directions, no dur is a no-op */ if (UNLIKELY(!(sdur = dur.dv))) { return t; } else if (sdur < 0) { downp = true; sdur = -sdur; } else if (dur.neg) { downp = true; } switch (dur.durtyp) { case DT_DURH: sdur *= MINS_PER_HOUR; /*@fallthrough@*/ case DT_DURM: sdur *= SECS_PER_MIN; /*@fallthrough@*/ case DT_DURS: /* only accept values whose remainder is 0 */ if (LIKELY(!(SECS_PER_DAY % (unsigned int)sdur))) { break; } /*@fallthrough@*/ default: return t; } /* unpack t */ with (unsigned int diff = t % (dt_sexy_t)sdur) { if (!diff && !nextp) { /* do nothing, i.e. really nothing, * in particular, don't set the slots again in the * assign section * this is not some obscure optimisation but to * support special notations like, military midnight * or leap seconds */ return t; } else if (!downp) { t += sdur - diff; } else if (!diff/* && downp && nextp*/) { t -= sdur; } else { t -= diff; } } return t; } static struct dt_dt_s dt_round(struct dt_dt_s d, struct dt_dtdur_s dur, bool nextp) { switch (d.typ) { default: switch (dur.durtyp) { default: /* all the date durs */ break; case DT_DURH: case DT_DURM: case DT_DURS: case DT_DURNANO: if (UNLIKELY(dt_sandwich_only_d_p(d))) { /* this doesn't make sense */ break; } if (!dur.cocl) { d.t = tround_tdur(d.t, dur, nextp); } else { d.t = tround_tdur_cocl(d.t, dur, nextp); } break; } /* check carry */ if (UNLIKELY(d.t.carry)) { /* we need to add a day */ struct dt_ddur_s one_day = dt_make_ddur(DT_DURD, d.t.carry); d.t.carry = 0; d.d = dt_dadd(d.d, one_day); } with (unsigned int sw = d.sandwich) { d.d = dround_ddur(d.d, dur.d, nextp); d.sandwich = (uint8_t)sw; } break; case DT_SEXY: case DT_SEXYTAI: if (UNLIKELY(!dur.cocl)) { error("Error: \ Epoch date/times have no divisions to round to."); break; } /* just keep it sexy */ d.sexy = sxround_dur_cocl(d.sexy, dur, nextp); break; } return d; } static struct dt_dt_s dround(struct dt_dt_s d, struct dt_dtdur_s dur[], size_t ndur, bool nextp) { for (size_t i = 0; i < ndur; i++) { d = dt_round(d, dur[i], nextp); } return d; } /* extended duration reader */ static int dt_io_strpdtrnd(struct __strpdtdur_st_s *st, const char *str) { char *sp = NULL; struct strpd_s d = strpd_initialiser(); struct dt_spec_s s = spec_initialiser(); struct dt_dtdur_s payload = {(dt_dtdurtyp_t)DT_DURUNK}; bool negp = false; bool coclp = true; if (dt_io_strpdtdur(st, str) >= 0) { return 0; } /* check for co-classes */ if (*str == '/') { coclp = true; str++; } /* check if there's a sign + or - */ if (*str == '-') { negp = true; str++; } else if (*str == '+') { str++; } /* try weekdays, set up s */ s.spfl = DT_SPFL_S_WDAY; s.abbr = DT_SPMOD_NORM; if (__strpd_card(&d, str, s, &sp) >= 0) { #if defined HAVE_ANON_STRUCTS_INIT payload.d = (struct dt_ddur_s){ DT_DURYMCW, .neg = negp, .cocl = coclp, .ymcw.w = d.w, }; #else payload.d.durtyp = DT_DURYMCW; payload.d.neg = negp; payload.d.cocl = coclp; payload.d.ymcw.w = d.w; #endif goto out; } /* try months, set up s */ s.spfl = DT_SPFL_S_MON; s.abbr = DT_SPMOD_NORM; if (__strpd_card(&d, str, s, &sp) >= 0) { #if defined HAVE_ANON_STRUCTS_INIT payload.d = (struct dt_ddur_s){ DT_DURYMD, .neg = negp, .ymd.m = d.m, }; #else payload.d.durtyp = DT_DURYMD; payload.d.neg = negp; payload.d.ymd.m = d.m; #endif goto out; } /* bugger */ st->istr = str; return -1; out: st->sign = 0; st->cont = NULL; return __add_dur(st, payload); } struct prln_ctx_s { struct grep_atom_soa_s *ndl; const char *ofmt; zif_t fromz; zif_t outz; int sed_mode_p; int quietp; const struct __strpdtdur_st_s *st; bool nextp; }; static int proc_line(struct prln_ctx_s ctx, char *line, size_t llen) { struct dt_dt_s d; char *sp = NULL; char *ep = NULL; int rc = 0; do { /* check if line matches, */ d = dt_io_find_strpdt2( line, llen, ctx.ndl, &sp, &ep, ctx.fromz); if (!dt_unk_p(d)) { if (UNLIKELY(d.fix) && !ctx.quietp) { rc = 2; } /* perform addition now */ d = dround(d, ctx.st->durs, ctx.st->ndurs, ctx.nextp); if (ctx.fromz != NULL) { /* fixup zone */ d = dtz_forgetz(d, ctx.fromz); } if (ctx.sed_mode_p) { __io_write(line, sp - line, stdout); dt_io_write(d, ctx.ofmt, ctx.outz, '\0'); llen -= (ep - line); line = ep; } else { dt_io_write(d, ctx.ofmt, ctx.outz, '\n'); break; } } else if (ctx.sed_mode_p) { line[llen] = '\n'; __io_write(line, llen + 1, stdout); break; } else { /* obviously unmatched, warn about it in non -q mode */ if (!ctx.quietp) { dt_io_warn_strpdt(line); rc = 2; } break; } } while (1); return rc; } #include "dround.yucc" int main(int argc, char *argv[]) { yuck_t argi[1U]; struct dt_dt_s d; struct __strpdtdur_st_s st = __strpdtdur_st_initialiser(); char *inp; const char *ofmt; char **fmt; size_t nfmt; int rc = 0; bool dt_given_p = false; bool nextp = false; zif_t fromz = NULL; zif_t z = NULL; if (yuck_parse(argi, argc, argv)) { rc = 1; goto out; } else if (argi->nargs == 0U) { error("Error: DATE or DURATION must be specified\n"); yuck_auto_help(argi); rc = 1; goto out; } /* init and unescape sequences, maybe */ ofmt = argi->format_arg; fmt = argi->input_format_args; nfmt = argi->input_format_nargs; if (argi->backslash_escapes_flag) { dt_io_unescape(argi->format_arg); for (size_t i = 0; i < nfmt; i++) { dt_io_unescape(fmt[i]); } } if (argi->from_locale_arg) { setilocale(argi->from_locale_arg); } if (argi->locale_arg) { setflocale(argi->locale_arg); } /* try and read the from and to time zones */ if (argi->from_zone_arg) { fromz = dt_io_zone(argi->from_zone_arg); } if (argi->zone_arg) { z = dt_io_zone(argi->zone_arg); } if (argi->next_flag) { nextp = true; } if (argi->base_arg) { struct dt_dt_s base = dt_strpdt(argi->base_arg, NULL, NULL); dt_set_base(base); } /* check first arg, if it's a date the rest of the arguments are * durations, if not, dates must be read from stdin */ dt_given_p = !dt_unk_p(d = dt_io_strpdt(*argi->args, fmt, nfmt, NULL)); for (size_t i = dt_given_p; i < argi->nargs; i++) { inp = argi->args[i]; do { if (dt_io_strpdtrnd(&st, inp) < 0) { if (UNLIKELY(i == 0)) { /* that's ok, must be a date then */ dt_given_p = true; } else { serror("Error: \ cannot parse duration/rounding string `%s'", st.istr); } } } while (__strpdtdur_more_p(&st)); } /* sanity checks */ if (dt_given_p) { /* date parsing needed postponing as we need to find out * about the durations * Also from-zone conversion needs postponing as we define * the conversion to take place on the rounded date */ inp = argi->args[0U]; if (dt_unk_p(d = dt_io_strpdt(inp, fmt, nfmt, NULL))) { error("Error: \ cannot interpret date/time string `%s'", argi->args[0U]); rc = 1; goto out; } } else if (st.ndurs == 0) { error("Error: \ no durations given"); rc = 1; goto out; } /* start the actual work */ if (dt_given_p) { if (UNLIKELY(d.fix) && !argi->quiet_flag) { rc = 2; } if (!dt_unk_p(d = dround(d, st.durs, st.ndurs, nextp))) { if (fromz != NULL) { /* fixup zone */ d = dtz_forgetz(d, fromz); } dt_io_write(d, ofmt, z, '\n'); } else { rc = 1; } } else { /* read from stdin */ size_t lno = 0; struct grep_atom_s __nstk[16], *needle = __nstk; size_t nneedle = countof(__nstk); struct grep_atom_soa_s ndlsoa; void *pctx; struct prln_ctx_s prln = { .ndl = &ndlsoa, .ofmt = ofmt, .fromz = fromz, .outz = z, .sed_mode_p = argi->sed_mode_flag, .quietp = argi->quiet_flag, .st = &st, .nextp = nextp, }; /* no threads reading this stream */ __io_setlocking_bycaller(stdout); /* lest we overflow the stack */ if (nfmt >= nneedle) { /* round to the nearest 8-multiple */ nneedle = (nfmt | 7) + 1; needle = calloc(nneedle, sizeof(*needle)); } /* and now build the needle */ ndlsoa = build_needle(needle, nneedle, fmt, nfmt); /* using the prchunk reader now */ if ((pctx = init_prchunk(STDIN_FILENO)) == NULL) { serror("Error: could not open stdin"); goto ndl_free; } while (prchunk_fill(pctx) >= 0) { for (char *line; prchunk_haslinep(pctx); lno++) { size_t llen = prchunk_getline(pctx, &line); rc |= proc_line(prln, line, llen); } } /* get rid of resources */ free_prchunk(pctx); ndl_free: if (needle != __nstk) { free(needle); } goto out; } /* free the strpdur status */ __strpdtdur_free(&st); dt_io_clear_zones(); if (argi->from_locale_arg) { setilocale(NULL); } if (argi->locale_arg) { setflocale(NULL); } out: yuck_free(argi); return rc; } /* dround.c ends here */ dateutils-0.4.5/src/dround.yuck000066400000000000000000000103141335042257000164750ustar00rootroot00000000000000Usage: dateround [OPTION]... [DATE/TIME] RNDSPEC... Round DATE/TIME to the next occurrence of RNDSPEC. If DATE/TIME is omitted a stream of date/times is read from stdin. DATE/TIME can also be one of the following specials - `now' interpreted as the current (UTC) time stamp - `time' the time part of the current (UTC) time stamp - `today' the current date (according to UTC) - `tomo[rrow]' tomorrow's date (according to UTC) - `y[ester]day' yesterday's date (according to UTC) RNDSPECs can be month names (Jan, Feb, ...), weekday names (Sun, Mon, ...), or days. If a month name the next date/time relative to DATE/TIME is returned whose month part matches the value given, so e.`g. dround 2012-01-01 Feb' will return 2012-02-01. If a weekday name is given, the next date/time after DATE/TIME whose weekday part matches the values given is returned. If a day, the next date/time after DATE/TIME whose day part matches is returned, so `dround 2012-01-15 1' will return 2012-02-01. RNDSPECs can also be multiples of the day dividing units, e.g 1h rounds to the nearest full hour, 30m to the nearest half hour, and 10s to the next 10s mark. To round to the previous occurrence of a RNDSPEC any argument can be prefixed with a `-' to denote that. E.g. `dround 2012-02-14 -1' will return 2012-02-01. And `dround 2012-02-11 -- -Sep' will return 2011-09-11. Multiple RNDSPECs are evaluated left to right. Note that rounding isn't commutative, e.g. 2012-03-01 Sat Sep -> 2012-09-03 vs. 2012-03-01 Sep Sat -> 2012-09-01 Note that non-numeric strings prefixed with a `-' conflict with the command line options and a separating `--' has to be used. -h, --help Print help and exit -V, --version Print version and exit -q, --quiet Suppress message about date/time and duration parser errors and fix-ups. The default is to print a warning or the fixed up value and return error code 2. -f, --format=STRING Output format. This can either be a specifier string (similar to strftime()'s FMT) or the name of a calendar. -i, --input-format=STRING... Input format, can be used multiple times. Each date/time will be passed to the input format parsers in the order they are given, if a date/time can be read successfully with a given input format specifier string, that value will be used. -b, --base=DT For underspecified input use DT as a fallback to fill in missing fields. Also used for ambiguous format specifiers to position their range on the absolute time line. Must be a date/time in ISO8601 format. If omitted defaults to the current date/time. -e, --backslash-escapes Enable interpretation of backslash escapes in the output and input format specifier strings. -S, --sed-mode Copy parts from the input before and after a matching date/time. Note that all occurrences of date/times within a line will be processed. --locale=LOCALE Format results according to LOCALE, this would only affect month and weekday names. --from-locale=LOCALE Interpret dates on stdin or the command line as coming from the locale LOCALE, this would only affect month and weekday names as input formats have to be specified explicitly. --from-zone=ZONE Interpret dates on stdin or the command line as coming from the time zone ZONE. -z, --zone=ZONE Convert dates printed on stdout to time zone ZONE, default: UTC. -n, --next Always round to a different date or time. dateutils-0.4.5/src/dseq.c000066400000000000000000000407551335042257000154210ustar00rootroot00000000000000/*** dseq.c -- like seq(1) but for dates * * Copyright (C) 2009 - 2011 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of dateutils. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***/ #if defined HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #include "dt-core.h" #include "dt-io.h" #include "dt-locale.h" #include "tzraw.h" typedef uint8_t __skipspec_t; /* generic closure */ struct dseq_clo_s { struct dt_dt_s fst; struct dt_dt_s lst; struct dt_dtdur_s *ite; size_t nite; struct dt_dtdur_s *altite; __skipspec_t ss; size_t naltite; /* direction, >0 if increasing, <0 if decreasing, 0 if undefined */ int dir; int flags; #define CLO_FL_FREE_ITE (1) }; const char *prog = "dseq"; /* skip system */ static int skipp(__skipspec_t ss, struct dt_dt_s dt) { dt_dow_t dow; /* common case first */ if (ss == 0) { return 0; } dow = dt_get_wday(dt.d); /* just check if the bit in the bitset `skip' is set */ return (ss & (1 << dow)) != 0; } #define SKIP_MON (1 << DT_MONDAY) #define SKIP_TUE (1 << DT_TUESDAY) #define SKIP_WED (1 << DT_WEDNESDAY) #define SKIP_THU (1 << DT_THURSDAY) #define SKIP_FRI (1 << DT_FRIDAY) #define SKIP_SAT (1 << DT_SATURDAY) #define SKIP_SUN (1 << DT_SUNDAY) static inline int __toupper(int c) { return c & ~0x20; } static dt_dow_t __parse_wd(const char *str) { #define ILEA(a, b) (((a) << 8) | (b)) int s1 = __toupper(str[0]); int s2 = __toupper(str[1]); switch (ILEA(s1, s2)) { case ILEA('M', 'O'): case ILEA('M', 0): /* monday */ return DT_MONDAY; case ILEA('T', 'U'): /* tuesday */ return DT_TUESDAY; case ILEA('W', 'E'): case ILEA('W', 0): /* wednesday */ return DT_WEDNESDAY; case ILEA('T', 'H'): /* thursday */ return DT_THURSDAY; case ILEA('F', 'R'): case ILEA('F', 0): /* friday */ return DT_FRIDAY; case ILEA('S', 'A'): case ILEA('A', 0): /* saturday */ return DT_SATURDAY; case ILEA('S', 'U'): case ILEA('S', 0): /* sunday */ return DT_SUNDAY; default: return DT_MIRACLEDAY; } } static __skipspec_t __skip_dow(__skipspec_t ss, unsigned int wd) { if (wd > GREG_DAYS_P_WEEK) { wd -= GREG_DAYS_P_WEEK; } switch (wd) { case DT_MONDAY: /* monday */ ss |= SKIP_MON; break; case DT_TUESDAY: /* tuesday */ ss |= SKIP_TUE; break; case DT_WEDNESDAY: /* wednesday */ ss |= SKIP_WED; break; case DT_THURSDAY: /* thursday */ ss |= SKIP_THU; break; case DT_FRIDAY: /* friday */ ss |= SKIP_FRI; break; case DT_SATURDAY: /* saturday */ ss |= SKIP_SAT; break; case DT_SUNDAY: /* sunday */ ss |= SKIP_SUN; break; default: case DT_MIRACLEDAY: break; } return ss; } static __skipspec_t __skip_str(__skipspec_t ss, const char *str) { dt_dow_t tmp; if ((tmp = __parse_wd(str)) != DT_MIRACLEDAY) { ss = __skip_dow(ss, tmp); } else { int s1 = __toupper(str[0]); int s2 = __toupper(str[1]); if (ILEA(s1, s2) == ILEA('S', 'S')) { /* weekend */ ss |= SKIP_SAT; ss |= SKIP_SUN; } } return ss; } static __skipspec_t __skip_1spec(__skipspec_t ss, char *spec) { char *tmp; dt_dow_t from, till; if ((tmp = strchr(spec, '-')) == NULL) { return __skip_str(ss, spec); } /* otherwise it's a range */ *tmp = '\0'; from = __parse_wd(spec); till = __parse_wd(tmp + 1); for (int d = from, e = till >= from ? till : till + 7; d <= e; d++) { ss = __skip_dow(ss, d); } return ss; } static __skipspec_t set_skip(__skipspec_t ss, char *spec) { char *tmp, *tm2; if ((tmp = strchr(spec, ',')) == NULL) { return __skip_1spec(ss, spec); } /* const violation */ *tmp++ = '\0'; ss = __skip_1spec(ss, spec); while ((tmp = strchr(tm2 = tmp, ','))) { *tmp++ = '\0'; ss = __skip_1spec(ss, tm2); } return __skip_1spec(ss, tm2); } static struct dt_dt_s date_add(struct dt_dt_s d, struct dt_dtdur_s dur[], size_t ndur) { int32_t carries = d.d.u; for (size_t i = 0; i < ndur; i++) { d = dt_dtadd(d, dur[i]); /* keep track of carries */ carries += d.t.carry; } if (UNLIKELY(dt_sandwich_only_t_p(d))) { d.d.u = carries; } return d; } static void date_neg_dur(struct dt_dtdur_s dur[], size_t ndur) { for (size_t i = 0; i < ndur; i++) { dur[i] = dt_neg_dtdur(dur[i]); } return; } static bool __daisy_feasible_p(struct dt_dtdur_s dur[], size_t ndur) { if (ndur != 1) { return false; } switch (dur->d.durtyp) { case DT_DURYMD: return !(dur->d.ymd.y || dur->d.ymd.m); case DT_DURBIZDA: return !dur->d.bizda.bd; case DT_DURD: case DT_DURBD: /* definitley, they're daisy already */ return true; case DT_DURWK: /* borderline, could be less efficient for ywd dates */ return true; case DT_DURMO: case DT_DURQU: case DT_DURYR: /* most definitely not */ default: /* all the time durs make it infeasible as well */ return false; } /* not reached */ } static bool __dur_naught_p(struct dt_dtdur_s dur) { /* we use the fact that dur.dv overlaps dur.d.dv */ return dur.dv == 0; } static bool __durstack_naught_p(struct dt_dtdur_s dur[], size_t ndur) { if (ndur == 0) { return true; } else if (ndur == 1) { return __dur_naught_p(dur[0]); } for (size_t i = 0; i < ndur; i++) { if (!__dur_naught_p(dur[i])) { return false; } } return true; } static bool __in_range_p(struct dt_dt_s now, const struct dseq_clo_s *clo) { if (!dt_sandwich_only_t_p(now)) { if (clo->dir > 0) { return dt_dt_in_range_p(now, clo->fst, clo->lst) == 1; } else if (clo->dir < 0) { return dt_dt_in_range_p(now, clo->lst, clo->fst) == 1; } } /* otherwise perform a simple range check */ if (clo->dir > 0) { if (clo->fst.t.u < clo->lst.t.u) { /* dseq A B with A < B */ return now.t.u >= clo->fst.t.u && now.t.u <= clo->lst.t.u; } else { /* dseq A B with A > B and wrap-around, * carries have kindly been stored in d.u */ return now.t.u <= clo->lst.t.u || now.d.u == 0U; } } else if (clo->dir < 0) { if (clo->fst.t.u > clo->lst.t.u) { /* counting down from A to B */ return now.t.u <= clo->fst.t.u && now.t.u >= clo->lst.t.u; } else { /* count down from A to B with wrap around, * carries have kindly been stored in d.u */ return now.t.u >= clo->lst.t.u || now.d.u == 0U; } } return false; } static struct dt_dt_s __seq_altnext(struct dt_dt_s now, const struct dseq_clo_s *clo) { do { now = date_add(now, clo->altite, clo->naltite); } while (skipp(clo->ss, now) && __in_range_p(now, clo)); return now; } static struct dt_dt_s __seq_this(struct dt_dt_s now, const struct dseq_clo_s *clo) { /* if NOW is on a skip date, find the next date according to ALTITE, then ITE */ if (!skipp(clo->ss, now) && __in_range_p(now, clo)) { return now; } else if (clo->naltite > 0) { return __seq_altnext(now, clo); } else if (clo->nite) { /* advance until it goes out of range */ for (; skipp(clo->ss, now) && __in_range_p(now, clo); now = date_add(now, clo->ite, clo->nite)); } else { /* good question */ ; } return now; } static struct dt_dt_s __seq_next(struct dt_dt_s now, const struct dseq_clo_s *clo) { /* advance NOW, then fix it */ struct dt_dt_s tmp = date_add(now, clo->ite, clo->nite); return __seq_this(tmp, clo); } static int __get_dir(struct dt_dt_s d, const struct dseq_clo_s *clo) { if (!dt_sandwich_only_t_p(d)) { /* trial addition to to see where it goes */ struct dt_dt_s tmp = __seq_next(d, clo); return dt_dtcmp(tmp, d); } if (clo->ite->dv > 0) { return 1; } else if (clo->ite->dv < 0) { return -1; } return 0; } static struct dt_dt_s __fixup_fst(struct dseq_clo_s *clo) { struct dt_dt_s tmp; struct dt_dt_s old; /* assume clo->dir has been computed already */ old = tmp = clo->lst; date_neg_dur(clo->ite, clo->nite); while (__in_range_p(tmp, clo)) { old = tmp; tmp = __seq_next(tmp, clo); } /* final checks */ old = __seq_this(old, clo); date_neg_dur(clo->ite, clo->nite); /* fixup again with negated dur */ old = __seq_this(old, clo); return old; } static struct dt_dtdur_s tseq_guess_ite(struct dt_t_s beg, struct dt_t_s end) { struct dt_dtdur_s res = {(dt_dtdurtyp_t)DT_DURUNK}; if (beg.hms.h != end.hms.h && beg.hms.m == 0 && end.hms.m == 0 && beg.hms.s == 0 && end.hms.s == 0) { res.durtyp = DT_DURH; res.dv = (beg.u < end.u) ? 1 : -1; } else if (beg.hms.m != end.hms.m && beg.hms.s == 0 && end.hms.s == 0) { res.durtyp = DT_DURM; res.dv = (beg.u < end.u) ? 1 : -1; } else { res.durtyp = DT_DURS; res.dv = (beg.u < end.u) ? 1 : -1; } return res; } #include "dseq.yucc" int main(int argc, char *argv[]) { static struct dt_dtdur_s ite_p1; yuck_t argi[1U]; struct dt_dt_s tmp; char **ifmt; size_t nifmt; char *ofmt; dt_dttyp_t tgttyp; int rc = 0; struct dseq_clo_s clo = { .ite = &ite_p1, .nite = 1, .altite = NULL, .naltite = 0, .ss = 0, .dir = 0, .flags = 0, }; if (yuck_parse(argi, argc, argv)) { rc = 1; goto out; } /* assign ofmt/ifmt */ ofmt = argi->format_arg; if (argi->backslash_escapes_flag) { dt_io_unescape(ofmt); } nifmt = argi->input_format_nargs; ifmt = argi->input_format_args; if (argi->from_locale_arg) { setilocale(argi->from_locale_arg); } if (argi->locale_arg) { setflocale(argi->locale_arg); } if (argi->base_arg) { struct dt_dt_s base = dt_strpdt(argi->base_arg, NULL, NULL); dt_set_base(base); } for (size_t i = 0; i < argi->skip_nargs; i++) { clo.ss = set_skip(clo.ss, argi->skip_args[i]); } if (argi->alt_inc_arg) { struct __strpdtdur_st_s st = __strpdtdur_st_initialiser(); do { if (dt_io_strpdtdur(&st, argi->alt_inc_arg) < 0) { if (!argi->quiet_flag) { error("Error: \ cannot parse duration string `%s'", argi->alt_inc_arg); } rc = 1; goto out; } } while (__strpdtdur_more_p(&st)); /* assign values */ clo.altite = st.durs; clo.naltite = st.ndurs; } switch (argi->nargs) { struct dt_dt_s fst, lst; default: yuck_auto_help(argi); rc = 1; goto out; case 2: lst = dt_io_strpdt(argi->args[1U], ifmt, nifmt, NULL); if (dt_unk_p(lst)) { if (!argi->quiet_flag) { dt_io_warn_strpdt(argi->args[1U]); } rc = 1; goto out; } else if (UNLIKELY(lst.fix) && !argi->quiet_flag) { rc = 2; } /* fallthrough */ case 1: fst = dt_io_strpdt(argi->args[0U], ifmt, nifmt, NULL); if (dt_unk_p(fst)) { if (!argi->quiet_flag) { dt_io_warn_strpdt(argi->args[0U]); } rc = 1; goto out; } else if (UNLIKELY(fst.fix) && !argi->quiet_flag) { rc = 2; } /* check the input arguments and do the sane thing now * if it's all dates, use DURD iterator * if it's all times, use DURS/DURM/DURH iterators * if one of them is a dt, promote the other */ if (dt_sandwich_only_d_p(fst)) { /* emulates old dseq(1) */ if (argi->nargs == 1U) { lst.d = dt_date(fst.d.typ); dt_make_d_only(&lst, fst.d.typ); } clo.ite->d = dt_make_ddur(DT_DURD, 1); } else if (dt_sandwich_only_t_p(fst)) { /* emulates old tseq(1) */ if (argi->nargs == 1U) { lst.t = dt_time(); dt_make_t_only(&lst, DT_HMS); } } else if (dt_sandwich_p(fst)) { if (argi->nargs == 1U) { lst = dt_datetime(fst.typ); dt_make_sandwich(&lst, fst.d.typ, DT_HMS); } clo.ite->d = dt_make_ddur(DT_DURD, 1); } else { error("\ don't know how to handle single argument case"); rc = 1; goto out; } goto make_compat; case 3: { struct __strpdtdur_st_s st = __strpdtdur_st_initialiser(); /* get lower bound */ fst = dt_io_strpdt(argi->args[0U], ifmt, nifmt, NULL); if (dt_unk_p(fst)) { if (!argi->quiet_flag) { dt_io_warn_strpdt(argi->args[0U]); } rc = 1; goto out; } else if (UNLIKELY(fst.fix) && !argi->quiet_flag) { rc = 2; } /* get increment */ do { if (dt_io_strpdtdur(&st, argi->args[1U]) < 0) { error("Error: \ cannot parse duration string `%s'", argi->args[1U]); rc = 1; goto out; } } while (__strpdtdur_more_p(&st)); /* assign values */ clo.ite = st.durs; clo.nite = st.ndurs; clo.flags |= CLO_FL_FREE_ITE; /* get upper bound */ lst = dt_io_strpdt(argi->args[2U], ifmt, nifmt, NULL); if (dt_unk_p(lst)) { if (!argi->quiet_flag) { dt_io_warn_strpdt(argi->args[2U]); } rc = 1; goto out; } else if (UNLIKELY(lst.fix) && !argi->quiet_flag) { rc = 2; } goto make_compat; } make_compat: if (LIKELY(fst.typ == lst.typ)) { clo.fst = fst; clo.lst = lst; } else { clo.fst = fst; clo.lst = dt_dtconv(fst.typ, lst); } break; } /* promote the args maybe */ if ((dt_sandwich_only_d_p(clo.fst) && dt_sandwich_only_t_p(clo.lst)) || (dt_sandwich_only_t_p(clo.fst) && dt_sandwich_only_d_p(clo.lst))) { error("\ cannot mix dates and times as arguments"); rc = 1; goto out; } else if (dt_sandwich_only_d_p(clo.fst) && dt_sandwich_p(clo.lst)) { /* promote clo.fst */ clo.fst.t = clo.lst.t; dt_make_sandwich(&clo.fst, clo.fst.d.typ, clo.lst.t.typ); } else if (dt_sandwich_p(clo.fst) && dt_sandwich_only_d_p(clo.lst)) { /* promote clo.lst */ clo.lst.t = clo.fst.t; dt_make_sandwich(&clo.lst, clo.lst.d.typ, clo.fst.t.typ); } else if (dt_sandwich_only_t_p(clo.fst) && dt_sandwich_p(clo.lst)) { /* promote clo.fst */ clo.fst.d = clo.lst.d; dt_make_sandwich(&clo.fst, clo.fst.d.typ, clo.lst.t.typ); } else if (dt_sandwich_p(clo.fst) && dt_sandwich_only_t_p(clo.lst)) { /* promote clo.lst */ clo.lst.d = clo.fst.d; dt_make_sandwich(&clo.lst, clo.lst.d.typ, clo.fst.t.typ); } #define _DAISY ((dt_dttyp_t)DT_DAISY) tgttyp = clo.fst.typ; if ((dt_sandwich_p(clo.fst) || dt_sandwich_only_d_p(clo.fst)) && clo.fst.d.typ == DT_YMD && clo.fst.d.ymd.m == 0 && argi->nargs < 3U) { /* iterate year-wise */ clo.ite->d = dt_make_ddur(DT_DURYR, 1); } else if ((dt_sandwich_p(clo.fst) || dt_sandwich_only_d_p(clo.fst)) && clo.fst.d.typ == DT_YMD && clo.fst.d.ymd.d == 0 && argi->nargs < 3U) { /* iterate month-wise */ clo.ite->d = dt_make_ddur(DT_DURMO, 1); } else if (dt_sandwich_only_d_p(clo.fst) && __daisy_feasible_p(clo.ite, clo.nite) && clo.fst.d.typ == DT_YMD && /* convert to daisies */ ((clo.fst = dt_dtconv(_DAISY, clo.fst)).d.typ != DT_DAISY || (clo.lst = dt_dtconv(_DAISY, clo.lst)).d.typ != DT_DAISY)) { if (!argi->quiet_flag) { error("\ cannot convert calendric system internally"); } rc = 1; goto out; } else if (dt_sandwich_only_t_p(clo.fst) && clo.ite->dv == 0) { *clo.ite = tseq_guess_ite(clo.fst.t, clo.lst.t); } if (__durstack_naught_p(clo.ite, clo.nite) || !(clo.dir = __get_dir(clo.fst, &clo))) { if (!argi->quiet_flag) { error("\ increment must not be naught"); } rc = 1; goto out; } else if (argi->compute_from_last_flag) { tmp = __fixup_fst(&clo); } else { tmp = __seq_this(clo.fst, &clo); } for (; __in_range_p(dt_fixup(tmp), &clo); tmp = __seq_next(tmp, &clo)) { struct dt_dt_s tgt = tmp; if (LIKELY(ofmt == NULL)) { tgt = dt_dtconv(tgttyp, tmp); } dt_io_write(tgt, ofmt, NULL, '\n'); } out: /* free strpdur resources */ if (clo.ite && clo.flags & CLO_FL_FREE_ITE) { free(clo.ite); } if (clo.altite != NULL) { free(clo.altite); } if (argi->from_locale_arg) { setilocale(NULL); } if (argi->locale_arg) { setflocale(NULL); } yuck_free(argi); return rc; } /* dseq.c ends here */ dateutils-0.4.5/src/dseq.yuck000066400000000000000000000103431335042257000161400ustar00rootroot00000000000000Usage: dateseq [OPTION]... FIRST [[INCREMENT] LAST] Generate a sequence of date/times from FIRST to LAST, optionally in steps of INCREMENT (which defaults to `1d'). If LAST is omitted it defaults to `now' if FIRST is a date/time, or `today' if FIRST is a date, or `time' if FIRST is a time. The values of FIRST and LAST are always inclusive and no date/times before FIRST and no date/times after LAST will be printed. Negative INCREMENTs must be given, i.e. if FIRST is newer than LAST. -h, --help Print help and exit -V, --version Print version and exit -q, --quiet Suppress message about date/time and duration parser errors and fix-ups. The default is to print a warning or the fixed up value and return error code 2. -f, --format=STRING Output format. This can either be a specifier string (similar to strftime()'s FMT) or the name of a calendar. -i, --input-format=STRING... Input format, can be used multiple times. Each date/time will be passed to the input format parsers in the order they are given, if a date/time can be read successfully with a given input format specifier string, that value will be used. -b, --base=DT For underspecified input use DT as a fallback to fill in missing fields. Also used for ambiguous format specifiers to position their range on the absolute time line. Must be a date/time in ISO8601 format. If omitted defaults to the current date/time. -e, --backslash-escapes Enable interpretation of backslash escapes in the output and input format specifier strings. --locale=LOCALE Format results according to LOCALE, this would only affect month and weekday names. --from-locale=LOCALE Interpret dates on stdin or the command line as coming from the locale LOCALE, this would only affect month and weekday names as input formats have to be specified explicitly. -s, --skip=STRING... Skip weekdays specified by STRING. STRING can be a single weekday (Mon, Tue, etc.), and to skip several days the --skip option can be used multiple times. STRING can also be a comma-separated list of weekday names, or `ss' to skip weekends (sat+sun) altogether. STRING can also contain date ranges like `mo-we' for monday to wednesday. --alt-inc=STRING Alternative increment to use when a date is hit that is skipped as per --skip. This increment will be applied until a non-skipped date is reached. The special case `0' (default) deactivates alternative incrementing. A useful value could be `1d' for increasing sequences and `-1d' for decreasing sequences, so if a skipped date is encountered the next non-skipped date after/before will be used. --compute-from-last Compute a start value from LAST using INCREMENT. This option has an effect only when INCREMENT is not a divisor of the duration between FIRST and LAST. In such case, an alternative FIRST will be computed by consecutively subtracting INCREMENT from LAST until FIRST is hit or crossed. dateutils-0.4.5/src/dsort.c000066400000000000000000000173261335042257000156160ustar00rootroot00000000000000/*** dsort.c -- sort FILEs or stdin chronologically * * Copyright (C) 2011-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of dateutils. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * **/ #if defined HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #include #include #include "dt-core.h" #include "dt-io.h" #include "dt-locale.h" #include "prchunk.h" const char *prog = "dsort"; struct prln_ctx_s { struct grep_atom_soa_s *ndl; zif_t fromz; int outfd; }; struct sort_ctx_s { unsigned int revp:1U; unsigned int unqp:1U; }; static void safe_write(int fd, const char *buf, size_t bsz) { size_t tot = 0U; for (ssize_t nwr; tot < bsz && (nwr = write(fd, buf + tot, bsz - tot)) >= 0; tot += nwr); return; } static void proc_line(struct prln_ctx_s ctx, char *line, size_t llen) { struct dt_dt_s d; do { char buf[64U]; char *sp, *tp; char *bp = buf; const char *const ep = buf + sizeof(buf); /* find first occurrence then */ d = dt_io_find_strpdt2( line, llen, ctx.ndl, &sp, &tp, ctx.fromz); /* print line, first thing */ safe_write(ctx.outfd, line, llen); /* extend by separator */ *bp++ = '\001'; /* check if line matches */ if (!dt_unk_p(d)) { /* match! */ if (!dt_sandwich_only_t_p(d)) { bp += dt_strfdt(bp, ep - bp, "%F", d); } *bp++ = '\001'; if (!dt_sandwich_only_d_p(d)) { bp += dt_strfdt(bp, ep - bp, "%T", d); } } else { /* just two empty fields then, innit? */ *bp++ = '\001'; } /* finalise the line and print */ *bp++ = '\n'; safe_write(ctx.outfd, buf, bp - buf); } while (0); return; } static int proc_file(struct prln_ctx_s prln, const char *fn) { size_t lno = 0; void *pctx; int fd; if (fn == NULL) { /* stdin then innit */ fd = STDIN_FILENO; } else if ((fd = open(fn, O_RDONLY)) < 0) { serror("Error: cannot open file `%s'", fn); return -1; } /* using the prchunk reader now */ if ((pctx = init_prchunk(fd)) == NULL) { serror("Error: cannot read from `%s'", fn ?: ""); return -1; } while (prchunk_fill(pctx) >= 0) { for (char *line; prchunk_haslinep(pctx); lno++) { size_t llen = prchunk_getline(pctx, &line); proc_line(prln, line, llen); } } /* get rid of resources */ free_prchunk(pctx); close(fd); return 0; } /* helper children, sort(1) and cut(1) */ static pid_t spawn_sort(int *restrict infd, const int outfd, struct sort_ctx_s sopt) { static char *cmdline[16U] = {"sort", "-t", "-k2"}; pid_t sortp; /* to snarf off traffic from the child */ int intfd[2]; if (pipe(intfd) < 0) { serror("pipe setup to/from sort failed"); return -1; } switch ((sortp = vfork())) { case -1: /* i am an error */ serror("vfork for sort failed"); return -1; default: /* i am the parent */ close(intfd[0]); *infd = intfd[1]; /* close outfd here already */ close(outfd); return sortp; case 0:; char **cp = cmdline + 3U; /* i am the child */ if (sopt.revp) { *cp++ = "-r"; } if (sopt.unqp) { *cp++ = "-u"; } *cp++ = NULL; /* stdout -> outfd */ dup2(outfd, STDOUT_FILENO); /* *infd -> stdin */ dup2(intfd[0], STDIN_FILENO); close(intfd[1]); execvp("sort", cmdline); serror("execvp(sort) failed"); _exit(EXIT_FAILURE); } } static pid_t spawn_cut(int *restrict infd) { static char *const cmdline[] = {"cut", "-d", "-f1", NULL}; pid_t cutp; /* to snarf off traffic from the child */ int intfd[2]; if (pipe(intfd) < 0) { serror("pipe setup to/from cut failed"); return -1; } switch ((cutp = vfork())) { case -1: /* i am an error */ serror("vfork for cut failed"); return -1; default:; /* i am the parent */ close(intfd[0]); *infd = intfd[1]; return cutp; case 0:; /* i am the child */ dup2(intfd[0], STDIN_FILENO); close(intfd[1]); execvp("cut", cmdline); serror("execvp(cut) failed"); _exit(EXIT_FAILURE); } } #include "dsort.yucc" int main(int argc, char *argv[]) { yuck_t argi[1U]; char **fmt; size_t nfmt; zif_t fromz = NULL; int rc = 0; struct sort_ctx_s sopt = {0U}; if (yuck_parse(argi, argc, argv)) { rc = 1; goto out; } /* init and unescape sequences, maybe */ fmt = argi->input_format_args; nfmt = argi->input_format_nargs; if (argi->backslash_escapes_flag) { for (size_t i = 0; i < nfmt; i++) { dt_io_unescape(fmt[i]); } } if (argi->from_locale_arg) { setilocale(argi->from_locale_arg); } /* try and read the from and to time zones */ if (argi->from_zone_arg) { fromz = dt_io_zone(argi->from_zone_arg); } if (argi->base_arg) { struct dt_dt_s base = dt_strpdt(argi->base_arg, NULL, NULL); dt_set_base(base); } /* prepare a mini-argi for the sort invocation */ if (argi->reverse_flag) { sopt.revp = 1U; } if (argi->unique_flag) { sopt.unqp = 1U; } { /* process all files */ struct grep_atom_s __nstk[16], *needle = __nstk; size_t nneedle = countof(__nstk); struct grep_atom_soa_s ndlsoa; struct prln_ctx_s prln = { .ndl = &ndlsoa, .fromz = fromz, }; pid_t cutp, sortp; /* lest we overflow the stack */ if (nfmt >= nneedle) { /* round to the nearest 8-multiple */ nneedle = (nfmt | 7) + 1; needle = calloc(nneedle, sizeof(*needle)); } /* and now build the needles */ ndlsoa = build_needle(needle, nneedle, fmt, nfmt); /* spawn children */ with (int ifd, ofd) { if ((cutp = spawn_cut(&ifd)) < 0) { goto ndl_free; } if ((sortp = spawn_sort(&ofd, ifd, sopt)) < 0) { goto ndl_free; } prln.outfd = ofd; } for (size_t i = 0U; i < argi->nargs || i == 0U; i++) { if (proc_file(prln, argi->args[i]) < 0) { rc = 1; } } /* indicate we're no longer writing to the sort helper */ close(prln.outfd); /* wait for sort first */ with (int st) { while (waitpid(sortp, &st, 0) != sortp); if (WIFEXITED(st) && WEXITSTATUS(st)) { rc = rc ?: WEXITSTATUS(st); } } /* wait for cut then */ with (int st) { while (waitpid(cutp, &st, 0) != cutp); if (WIFEXITED(st) && WEXITSTATUS(st)) { rc = rc ?: WEXITSTATUS(st); } } ndl_free: if (needle != __nstk) { free(needle); } } dt_io_clear_zones(); if (argi->from_locale_arg) { setilocale(NULL); } out: yuck_free(argi); return rc; } /* dsort.c ends here */ dateutils-0.4.5/src/dsort.yuck000066400000000000000000000040211335042257000163330ustar00rootroot00000000000000Usage: datesort [OPTION]... [FILE]... Sort contents of FILE chronologically. If FILE is omitted read from stdin. The first date/time value per line is the sort key. Dates without times account for a smaller value than any date/time on the same day. Times without dates account for a smaller value than any date or date/time. If a line contains no dates or times or date/times it is sorted towards the front. -h, --help Print help and exit -V, --version Print version and exit -i, --input-format=STRING... Input format, can be used multiple times. Each date/time will be passed to the input format parsers in the order they are given, if a date/time can be read successfully with a given input format specifier string, that value will be used. -b, --base=DT For underspecified input use DT as a fallback to fill in missing fields. Also used for ambiguous format specifiers to position their range on the absolute time line. Must be a date/time in ISO8601 format. If omitted defaults to the current date/time. -e, --backslash-escapes Enable interpretation of backslash escapes in the input format specifier strings. --from-locale=LOCALE Interpret dates on stdin or the command line as coming from the locale LOCALE, this would only affect month and weekday names as input formats have to be specified explicitly. --from-zone=ZONE Interpret dates on stdin or the command line as coming from the time zone ZONE. -r, --reverse Reverse the sort order. -u, --unique Print at most one line per date/time value.dateutils-0.4.5/src/dt-io-zone.c000066400000000000000000000110411335042257000164340ustar00rootroot00000000000000/*** dt-io-zone.c -- abstract from raw zone interface * * Copyright (C) 2010-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of dateutils. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***/ #if defined HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include #include "tzmap.h" #include "dt-io.h" #include "dt-io-zone.h" #include "alist.h" #if defined TZMAP_DIR static const char tmdir[] = TZMAP_DIR; #else /* !TZMAP_DIR */ static const char tmdir[] = "."; #endif /* TZMAP_DIR */ #define TZMAP_SUF ".tzmcc" static size_t xstrlncpy(char *restrict dst, size_t dsz, const char *src, size_t ssz) { if (ssz > dsz) { ssz = dsz - 1U; } memcpy(dst, src, ssz); dst[ssz] = '\0'; return ssz; } static size_t xstrlcpy(char *restrict dst, const char *src, size_t dsz) { size_t ssz = strlen(src); if (ssz > dsz) { ssz = dsz - 1U; } memcpy(dst, src, ssz); dst[ssz] = '\0'; return ssz; } /* extended zone handling, tzmaps and stuff */ #if !defined PATH_MAX # define PATH_MAX 256U #endif /* !PATH_MAX */ static struct alist_s zones[1U]; static struct alist_s tzmaps[1U]; static tzmap_t find_tzmap(const char *mnm, size_t mnz) { static const char tzmap_suffix[] = TZMAP_SUF; char tzmfn[PATH_MAX]; char *tp = tzmfn; size_t tz = sizeof(tzmfn); const char *p; size_t z; /* prefer TZMAP_DIR */ if ((p = getenv("TZMAP_DIR")) != NULL) { z = xstrlcpy(tp, p, tz); } else { z = xstrlncpy(tp, tz, tmdir, sizeof(tmdir) - 1U); } tp += z, tz -= z; *tp++ = '/', tz--; /* try and find it the hard way */ xstrlncpy(tp, tz, mnm, mnz); tp += mnz, tz -= mnz; xstrlncpy(tp, tz, tzmap_suffix, sizeof(tzmap_suffix) - 1U); /* try and open the thing, then try and look up SPEC */ return tzm_open(tzmfn); } static zif_t __io_zone(const char *spec) { zif_t res; /* try looking up SPEC first */ if ((res = alist_assoc(zones, spec)) == NULL) { /* open 'im */ if ((res = zif_open(spec)) != NULL) { /* cache 'im */ alist_put(zones, spec, res); } } return res; } zif_t dt_io_zone(const char *spec) { char *p; if (spec == NULL) { /* safety net */ return NULL; } /* see if SPEC is a MAP:KEY */ if ((p = strchr(spec, ':')) != NULL) { char tzmfn[PATH_MAX]; tzmap_t tzm; xstrlncpy(tzmfn, sizeof(tzmfn), spec, p - spec); /* check tzmaps alist first */ if ((tzm = alist_assoc(tzmaps, tzmfn)) != NULL) { ; } else if ((tzm = find_tzmap(tzmfn, p - spec)) != NULL) { /* cache the instance */ alist_put(tzmaps, tzmfn, tzm); } else { error("\ Cannot find `%s" TZMAP_SUF "' in the tzmaps search path\n\ Set TZMAP_DIR environment variable to where " TZMAP_SUF " files reside", tzmfn); return NULL; } /* look up key bit in tzmap and use that if found */ if ((spec = tzm_find(tzm, ++p)) == NULL) { return NULL; } } return __io_zone(spec); } void dt_io_clear_zones(void) { if (tzmaps->data != NULL) { for (acons_t c; (c = alist_next(tzmaps)).val;) { tzm_close(c.val); } free_alist(tzmaps); } if (zones->data != NULL) { for (acons_t c; (c = alist_next(zones)).val;) { zif_close(c.val); } free_alist(zones); } return; } /* dt-io-zone.c ends here */ dateutils-0.4.5/src/dt-io-zone.h000066400000000000000000000035341335042257000164510ustar00rootroot00000000000000/*** dt-io-zone.h -- abstract from raw zone interface * * Copyright (C) 2009-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of dateutils. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***/ #if !defined INCLUDED_dt_io_zone_h_ #define INCLUDED_dt_io_zone_h_ #include "tzraw.h" extern zif_t dt_io_zone(const char *spec); extern void dt_io_clear_zones(void); #endif /* INCLUDED_dt_io_zone_h_ */ dateutils-0.4.5/src/dt-io.c000066400000000000000000000412241335042257000154710ustar00rootroot00000000000000#if defined HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include #include #if defined __GLIBC__ /* for *_unlocked protos */ # include #endif /* __GLIBC__ */ /* for strstr() */ #include /* for strcasecmp() */ #include #include #include #include "dt-core.h" #include "dt-core-tz-glue.h" #include "date-core-private.h" #include "date-core-strpf.h" #include "dt-locale.h" #include "tzraw.h" #include "tzmap.h" #include "strops.h" #include "token.h" #include "nifty.h" #include "dt-io.h" #include "alist.h" #if defined __INTEL_COMPILER /* we MUST return a char* */ # pragma warning (disable:2203) #elif defined __GNUC__ # pragma GCC diagnostic ignored "-Wcast-qual" #endif /* __INTEL_COMPILER */ /* our own perror() implementation */ void __attribute__((format(printf, 1, 2))) error(const char *fmt, ...) { va_list vap; va_start(vap, fmt); fputs(prog, stderr); fputs(": ", stderr); vfprintf(stderr, fmt, vap); va_end(vap); fputc('\n', stderr); return; } void __attribute__((format(printf, 1, 2))) serror(const char *fmt, ...) { va_list vap; va_start(vap, fmt); fputs(prog, stderr); fputs(": ", stderr); vfprintf(stderr, fmt, vap); va_end(vap); if (errno) { fputc(':', stderr); fputc(' ', stderr); fputs(strerror(errno), stderr); } fputc('\n', stderr); return; } #include "strpdt-special.c" dt_strpdt_special_t dt_io_strpdt_special(const char *str) { size_t len = strlen(str); const struct dt_strpdt_special_s *res; if (UNLIKELY((res = __strpdt_special(str, len)) != NULL)) { return res->e; } return STRPDT_UNK; } struct dt_dt_s dt_io_strpdt_ep( const char *str, const char *const *fmt, size_t nfmt, char **ep, zif_t zone) { struct dt_dt_s res = dt_dt_initialiser(); dt_strpdt_special_t now; /* init */ if (ep != NULL) { *ep = NULL; } /* basic sanity checks, catch phrases first */ now = dt_io_strpdt_special(str); if (now > STRPDT_UNK) { res = dt_datetime((dt_dttyp_t)DT_YMD); /* rinse according to flags */ switch (now) { static signed int add[] = { [STRPDT_YDAY] = -1, [STRPDT_TOMO] = 1, }; case STRPDT_TOMO: case STRPDT_YDAY: case STRPDT_DATE: res.t = dt_t_initialiser(); dt_make_d_only(&res, res.d.typ); if (LIKELY(now == STRPDT_DATE)) { break; } res.d = dt_dadd(res.d, dt_make_ddur(DT_DURD, add[now])); break; case STRPDT_TIME: res.d = dt_d_initialiser(); dt_make_t_only(&res, res.t.typ); break; case STRPDT_NOW: case STRPDT_UNK: default: break; } return res; } else if (nfmt == 0) { res = dt_strpdt(str, NULL, ep); } else { for (size_t i = 0; i < nfmt; i++) { if (!dt_unk_p(res = dt_strpdt(str, fmt[i], ep))) { break; } } } return dtz_forgetz(res, zone); } struct dt_dt_s dt_io_find_strpdt( const char *str, char *const *fmt, size_t nfmt, const char *needle, size_t needlen, char **sp, char **ep, zif_t zone) { const char *__sp = str; struct dt_dt_s d; const char *const *cfmt = (const char*const*)fmt; d = dt_io_strpdt_ep(__sp, cfmt, nfmt, ep, zone); if (dt_unk_p(d)) { while ((__sp = strstr(__sp, needle)) && (d = dt_io_strpdt_ep( __sp += needlen, cfmt, nfmt, ep, zone), dt_unk_p(d))); } *sp = (char*)__sp; return d; } struct dt_dt_s dt_io_find_strpdt2( const char *str, size_t len, const struct grep_atom_soa_s *needles, char **sp, char **ep, zif_t zone) { struct dt_dt_s d = dt_dt_initialiser(); const char *needle = needles->needle; const char *p = str; const char *const zp = str + len; for (; *(p = xmempbrk(p, zp - p, needle)); p++) { /* find the offset */ const struct grpatm_payload_s *fp; const char *np; for (np = needle, fp = needles->flesh; *np < *p; np++, fp++); /* nc points to the first occurrence of *p in needle, * f is the associated grpatm payload */ while (*np++ == *p) { const struct grpatm_payload_s f = *fp++; const char *fmt = f.fmt; const char *q = p + f.off_min; const char *r = p + f.off_max; if (UNLIKELY(q < str)) { q = str; } for (; q < zp && q <= r; q++) { if (!dt_unk_p(d = dt_strpdt(q, fmt, ep))) { p = q; goto found; } } } } /* otherwise check character classes */ for (size_t i = 0; needle[i] == GRPATM_NEEDLELESS_MODE_CHAR; i++) { struct grpatm_payload_s f = needles->flesh[i]; const char *fmt = f.fmt; const char *ndl; /* look out for char classes*/ switch (f.flags) { /* this isn't the bestest of approaches as it involves * details about the contents behind the specifiers */ static const char a_needle[] = "FMSTWfmstw"; static const char ta_needle[] = "MTWRFAS"; static const char b_needle[] = "ADFJMNOSadfjmnos"; static const char tb_needle[] = "FGHJKMNQUVXZ"; static const char o_needle[] = "CDILMVXcdilmvx"; case GRPATM_A_SPEC: ndl = a_needle; break; case GRPATM_B_SPEC: ndl = b_needle; break; case GRPATM_TA_SPEC: ndl = ta_needle; break; case GRPATM_TB_SPEC: ndl = tb_needle; break; case GRPATM_O_SPEC: ndl = o_needle; break; case GRPATM_DIGITS: /* yay, look for all digits */ for (p = str; p < zp && !(*p >= '0' && *p <= '9'); p++); for (const char *q = p; q < zp && *q >= '0' && *q <= '9'; q++) { if ((--f.off_min <= 0) && !dt_unk_p(d = dt_strpdt(p, fmt, ep))) { goto found; } } continue; case GRPATM_DIGITS | GRPATM_ORDINALS: /* yay, look for all digits and ordinals */ for (p = str; p < zp && !(*p >= '0' && *p <= '9'); p++); for (const char *q = p; q < zp; q++) { switch (*q) { case '0' ... '9': break; case 't': if (*++q == 'h') { break; } goto bugger; case 's': if (*++q == 't') { break; } goto bugger; case 'n': case 'r': if (*++q == 'd') { break; } goto bugger; default: goto bugger; } if ((--f.off_min <= 0) && !dt_unk_p(d = dt_strpdt(p, fmt, ep))) { goto found; } } bugger: default: continue; } /* not reached unless ndl is set */ for (p = str; *(p = xmempbrk(p, zp - p, ndl)); p++) { if (p + f.off_min < str || p + f.off_max > zp) { continue; } for (int8_t j = f.off_min; j <= f.off_max; j++) { if (!dt_unk_p(d = dt_strpdt(p + j, fmt, ep))) { p += j; goto found; } } } } /* reset to some sane defaults */ *ep = (char*)(p = str); found: *sp = (char*)p; return dtz_forgetz(d, zone); } int dt_io_write(struct dt_dt_s d, const char *fmt, zif_t zone, int apnd_ch) { static char buf[256]; size_t n; if (zone != NULL) { d = dtz_enrichz(d, zone); } else { /* zone == NULL is UTC, kill zdiff */ d.zdiff = 0U; d.neg = 0U; } n = dt_io_strfdt(buf, sizeof(buf), fmt, d, apnd_ch); __io_write(buf, n, stdout); return (n > 0) - 1; } /* needles for the grep mode */ struct grep_atom_s calc_grep_atom(const char *fmt) { struct grep_atom_s res = __grep_atom_initialiser(); int8_t andl_idx = 0; int8_t bndl_idx = 0; int8_t pndl_idx = 0; /* init */ if (fmt == NULL) { dstd: /* standard format, %Y-%m-%d */ res.needle = '-'; res.pl.off_min = -4; res.pl.off_max = -4; goto out; tstd: /* standard format, %H:%M:%S */ res.needle = ':'; res.pl.off_min = -2; res.pl.off_max = -1; goto out; } else { /* try and transform shortcuts */ switch (__trans_dfmt(&fmt)) { default: break; case DT_LDN: case DT_JDN: case DT_MDN: /* there's no format specifiers for lilian/julian */ res.pl.off_min += -10; res.pl.off_max += -1; res.pl.flags |= GRPATM_DIGITS; goto post_snarf; } } /* rest here ... */ for (const char *fp = fmt; *fp;) { const char *fp_sav = fp; struct dt_spec_s spec = __tok_spec(fp_sav, &fp); /* pre checks */ if (spec.ord) { /* account for the extra 2 letters, but they're * optional now, so don't fiddle with the max bit */ res.pl.off_min -= 2; res.pl.flags |= GRPATM_ORDINALS; } #if 0 if (spec.bizda) { /* account for the extra suffix character, it's * optional again */ res.pl.off_min -= 1; res.pl.flags |= GRPATM_SUFFIX; } #endif switch (spec.spfl) { case DT_SPFL_UNK: /* found a non-spec character that can be * used as needle, we should check for the * character's suitability though, a space is not * the best needle to find in a haystack of * english text, in fact it's more like a haystack * itself */ res.needle = *fp_sav; goto out; case DT_SPFL_LIT_PERCENT: /* very good needle character methinks */ res.needle = '%'; goto out; case DT_SPFL_LIT_NL: /* quite good needle characters */ res.needle = '\n'; goto out; case DT_SPFL_LIT_TAB: res.needle = '\t'; goto out; case DT_SPFL_N_DSTD: goto dstd; case DT_SPFL_N_TSTD: goto tstd; case DT_SPFL_N_YEAR: switch (spec.abbr) { case DT_SPMOD_LONG: res.pl.off_min += -4; res.pl.off_max += -4; break; case DT_SPMOD_NORM: res.pl.off_min += -2; res.pl.off_max += -2; break; case DT_SPMOD_ABBR: res.pl.off_min += -1; res.pl.off_max += -1; break; case DT_SPMOD_ILL: default: /* should be impossible */ break; } res.pl.flags |= GRPATM_DIGITS; break; case DT_SPFL_N_MON: case DT_SPFL_N_DCNT_WEEK: case DT_SPFL_N_DCNT_MON: case DT_SPFL_N_WCNT_MON: case DT_SPFL_N_WCNT_YEAR: case DT_SPFL_N_QTR: case DT_SPFL_N_HOUR: case DT_SPFL_N_MIN: case DT_SPFL_N_SEC: res.pl.off_min += -2; res.pl.off_max += -1; res.pl.flags |= GRPATM_DIGITS; break; case DT_SPFL_S_WDAY: if (res.pl.off_min == res.pl.off_max) { andl_idx = res.pl.off_min; } switch (spec.abbr) { case DT_SPMOD_NORM: res.pl.off_min -= dut_rabbr_wday.max; res.pl.off_max -= dut_rabbr_wday.min; res.pl.flags |= GRPATM_A_SPEC; break; case DT_SPMOD_ABBR: res.pl.off_min -= 1; res.pl.off_max -= 1; res.pl.flags |= GRPATM_TA_SPEC; break; case DT_SPMOD_LONG: res.pl.off_min -= dut_rlong_wday.max; res.pl.off_max -= dut_rlong_wday.min; res.pl.flags |= GRPATM_A_SPEC; break; default: break; } break; case DT_SPFL_S_MON: if (res.pl.off_min == res.pl.off_max) { bndl_idx = res.pl.off_min; } switch (spec.abbr) { case DT_SPMOD_NORM: res.pl.off_min -= dut_rabbr_mon.max; res.pl.off_max -= dut_rabbr_mon.min; res.pl.flags |= GRPATM_B_SPEC; break; case DT_SPMOD_ABBR: res.pl.off_min -= 1; res.pl.off_max -= 1; res.pl.flags |= GRPATM_TB_SPEC; break; case DT_SPMOD_LONG: res.pl.off_min -= dut_rlong_mon.max; res.pl.off_max -= dut_rlong_mon.min; res.pl.flags |= GRPATM_B_SPEC; break; default: break; } break; case DT_SPFL_N_DCNT_YEAR: res.pl.off_min += -3; res.pl.off_max += -1; res.pl.flags |= GRPATM_DIGITS; break; case DT_SPFL_S_QTR: res.needle = 'Q'; goto out; case DT_SPFL_S_AMPM: res.pl.flags |= GRPATM_P_SPEC; if (res.pl.off_min == res.pl.off_max) { pndl_idx = res.pl.off_min; } res.pl.off_min += -2; res.pl.off_max += -2; break; case DT_SPFL_N_EPOCH: res.pl.off_min += -10; res.pl.off_max += -1; res.pl.flags |= GRPATM_DIGITS; break; default: break; } } post_snarf: if (res.needle == 0 && (res.pl.off_min || res.pl.off_max)) { if ((res.pl.flags & ~(GRPATM_DIGITS | GRPATM_ORDINALS)) == 0) { /* ah, only digits, thats good */ int8_t tmp = (int8_t)-res.pl.off_min; /* swap-invert min and max */ res.pl.off_min = (int8_t)-res.pl.off_max; res.pl.off_max = tmp; /* use a needle that is unlikely to occur and * that will bubble to the front of the needlestack */ res.needle = GRPATM_NEEDLELESS_MODE_CHAR; goto out; } else if (res.pl.flags & GRPATM_A_SPEC) { res.needle = GRPATM_NEEDLELESS_MODE_CHAR; res.pl.off_min = res.pl.off_max = andl_idx; res.pl.flags = GRPATM_A_SPEC; goto out; } else if (res.pl.flags & GRPATM_B_SPEC) { res.needle = GRPATM_NEEDLELESS_MODE_CHAR; res.pl.off_min = res.pl.off_max = bndl_idx; res.pl.flags = GRPATM_B_SPEC; goto out; } else if (res.pl.flags & GRPATM_O_SPEC) { res.needle = GRPATM_NEEDLELESS_MODE_CHAR; } else if (res.pl.flags & GRPATM_P_SPEC) { res.needle = GRPATM_NEEDLELESS_MODE_CHAR; res.pl.off_min = res.pl.off_max = pndl_idx; res.pl.flags = GRPATM_P_SPEC; goto out; } else if (res.pl.flags & GRPATM_TA_SPEC) { /* very short but better than going for digits aye? */ res.needle = GRPATM_NEEDLELESS_MODE_CHAR; res.pl.off_min = res.pl.off_max = andl_idx; res.pl.flags = GRPATM_TA_SPEC; goto out; } else if (res.pl.flags & GRPATM_TB_SPEC) { res.needle = GRPATM_NEEDLELESS_MODE_CHAR; res.pl.off_min = res.pl.off_max = bndl_idx; res.pl.flags = GRPATM_TB_SPEC; goto out; } } /* naught flags mean the usual needle char search */ res.pl.flags = 0; out: /* finally assign the format */ if (res.needle || res.pl.flags) { res.pl.fmt = fmt; } return res; } struct grep_atom_soa_s build_needle(grep_atom_t atoms, size_t natoms, char *const *fmt, size_t nfmt) { struct grep_atom_soa_s res = make_grep_atom_soa(atoms, natoms); struct grep_atom_s a; if (nfmt == 0) { /* inject the standard needles for %F and %T */ size_t idx; /* standard format %F */ idx = res.natoms++; res.needle[idx] = '-'; res.flesh[idx].off_min = -4; res.flesh[idx].off_max = -4; res.flesh[idx].fmt = NULL; /* standard format, %T */ idx = res.natoms++; res.needle[idx] = ':'; res.flesh[idx].off_min = -2; res.flesh[idx].off_max = -1; res.flesh[idx].fmt = NULL; goto out; } /* otherwise collect needles from all formats */ for (size_t i = 0; i < nfmt && res.natoms < natoms; i++) { if ((a = calc_grep_atom(fmt[i])).needle) { const char *ndl = res.needle; size_t idx = res.natoms++; size_t j; /* stable insertion sort, find the slot first ... */ for (j = 0; j < idx && ndl[j] <= a.needle; j++); /* ... j now points to where we insert, so move * everything behind j */ if (j < idx) { memmove(res.needle + j + 1, ndl + j, idx - j); memmove( res.flesh + j + 1, res.flesh + j, (idx - j) * sizeof(*res.flesh)); } res.needle[j] = a.needle; res.flesh[j] = a.pl; } } out: /* terminate needle with \0 */ res.needle[res.natoms] = '\0'; return res; } void dt_io_unescape(char *s) { static const char esc_map[] = "\a\bcd\e\fghijklm\nopq\rs\tu\v"; char *p, *q; if (UNLIKELY(s == NULL)) { return; } else if ((p = q = strchr(s, '\\')) != NULL) { do { if (*p != '\\' || !*++p) { *q++ = *p++; } else if (*p < 'a' || *p > 'v') { *q++ = *p++; } else { *q++ = esc_map[*p++ - 'a']; } } while (*p); *q = '\0'; } return; } /* duration parser */ /* we parse durations ourselves so we can cope with the * non-commutativity of duration addition: * 2000-03-30 +1m -> 2000-04-30 +1d -> 2000-05-01 * 2000-03-30 +1d -> 2000-03-31 +1m -> 2000-04-30 */ int __add_dur(struct __strpdtdur_st_s *st, struct dt_dtdur_s dur) { if (dt_durunk_p(dur)) { return -1; } if (st->durs == NULL) { st->durs = calloc(16, sizeof(*st->durs)); } else if ((st->ndurs % 16) == 0) { void *tmp; tmp = realloc(st->durs, (16 + st->ndurs) * sizeof(*st->durs)); if (UNLIKELY(tmp == NULL)) { return -1; } /* otherwise proceed as usual */ st->durs = tmp; memset(st->durs + st->ndurs, 0, 16 * sizeof(*st->durs)); } st->durs[st->ndurs++] = dur; return 0; } int dt_io_strpdtdur(struct __strpdtdur_st_s *st, const char *str) { /* at the moment we allow only one format */ const char *sp = NULL; const char *ep = NULL; int res = 0; /* check if we should continue */ if (st->cont != NULL) { str = st->istr = st->cont; } else if ((st->istr = str) != NULL) { ; } else { goto out; } /* read over signs and prefixes */ sp = str; while (1) { switch (*sp++) { case '\0': res = -1; ep = sp; goto out; case '+': st->sign = 1; break; case '-': st->sign = -1; break; case '=': if (st->sign > 0) { st->sign++; } else if (st->sign < 0) { st->sign--; } else { st->sign = 0; } break; case '>': st->sign = 2; break; case '<': st->sign = -2; break; case '/': st->flags = 1U; break; case 'p': case 'P': case ' ': case '\t': case '\n': continue; default: sp--; break; } break; } /* try reading the stuff with our strpdur() */ { struct dt_dtdur_s d = dt_strpdtdur(sp, (char**)&ep); if ((st->sign == 1 && dt_dtdur_neg_p(d)) || (st->sign == -1 && !dt_dtdur_neg_p(d))) { d = dt_neg_dtdur(d); } d.cocl = (bool)(st->flags & 0x1U); res = __add_dur(st, d); } out: if (((st->cont = ep) && *ep == '\0') || (sp == ep)) { st->sign = 0; st->cont = NULL; } return res; } #if defined __INTEL_COMPILER # pragma warning (default:2203) #elif defined __GNUC__ # pragma GCC diagnostic warning "-Wcast-qual" #endif /* __INTEL_COMPILER */ /* dt-io.c ends here */ dateutils-0.4.5/src/dt-io.h000066400000000000000000000136211335042257000154760ustar00rootroot00000000000000/*** dt-io.h -- helper for formats, parsing, printing, escaping, etc. */ #if !defined INCLUDED_dt_io_h_ #define INCLUDED_dt_io_h_ #include #include #if defined __GLIBC__ /* for *_unlocked protos */ # include #endif /* __GLIBC__ */ /* for strstr() */ #include /* for strcasecmp() */ #include #include "dt-core.h" #include "dt-io-zone.h" #include "nifty.h" typedef enum { STRPDT_UNK, STRPDT_DATE, STRPDT_TIME, STRPDT_NOW, STRPDT_YDAY, STRPDT_TOMO, } dt_strpdt_special_t; /* needles for the grep mode */ typedef struct grep_atom_s *grep_atom_t; typedef const struct gep_atom_s *const_grep_atom_t; struct grpatm_payload_s { uint16_t flags; #define GRPATM_DIGITS (1U) #define GRPATM_ORDINALS (2U) #define GRPATM_SUFFIX (4U) #define GRPATM_A_SPEC (8U) #define GRPATM_TA_SPEC (16U) #define GRPATM_B_SPEC (32U) #define GRPATM_TB_SPEC (64U) #define GRPATM_O_SPEC (128U) #define GRPATM_P_SPEC (256U) int8_t off_min; int8_t off_max; const char *fmt; }; /* atoms are maps needle-character -> payload */ struct grep_atom_s { /* 4 bytes it should be */ char needle; struct grpatm_payload_s pl; }; struct grep_atom_soa_s { size_t natoms; char *needle; struct grpatm_payload_s *flesh; }; /* duration parser */ /* we parse durations ourselves so we can cope with the * non-commutativity of duration addition: * 2000-03-30 +1m -> 2000-04-30 +1d -> 2000-05-01 * 2000-03-30 +1d -> 2000-03-31 +1m -> 2000-04-30 */ struct __strpdtdur_st_s { int sign; unsigned int flags; const char *istr; const char *cont; size_t ndurs; struct dt_dtdur_s *durs; }; /* public API */ extern dt_strpdt_special_t dt_io_strpdt_special(const char *str); extern struct dt_dt_s dt_io_strpdt_ep( const char *str, const char *const *fmt, size_t nfmt, char **ep, zif_t zone); extern struct dt_dt_s dt_io_find_strpdt( const char *str, char *const *fmt, size_t nfmt, const char *needle, size_t needlen, char **sp, char **ep, zif_t zone); extern struct dt_dt_s dt_io_find_strpdt2( const char *str, size_t llen, const struct grep_atom_soa_s *needles, char **sp, char **ep, zif_t zone); extern int dt_io_write(struct dt_dt_s d, const char *fmt, zif_t zone, int apnd_ch); /* grep atoms */ extern struct grep_atom_s calc_grep_atom(const char *fmt); extern struct grep_atom_soa_s build_needle(grep_atom_t atoms, size_t natoms, char *const *fmt, size_t nfmt); extern void dt_io_unescape(char *s); /* error messages, warnings, etc. */ extern __attribute__((format(printf, 1, 2))) void error(const char *fmt, ...); /* error messages, warnings, etc. */ extern __attribute__((format(printf, 1, 2))) void serror(const char *fmt, ...); /* for error() above, use PROG as name for the tool. */ extern const char *prog; /* duration parser */ extern int __add_dur(struct __strpdtdur_st_s *st, struct dt_dtdur_s dur); extern int dt_io_strpdtdur(struct __strpdtdur_st_s *st, const char *str); /* zone handling, tzmaps et al. */ extern zif_t dt_io_zone(const char *spec); /* inlines */ static inline struct dt_dt_s dt_io_strpdt(const char *input, char *const *fmt, size_t nfmt, zif_t zone) { return dt_io_strpdt_ep(input, (const char*const*)fmt, nfmt, NULL, zone); } /* grep atoms */ static inline __attribute__((pure, const)) struct grep_atom_s __grep_atom_initialiser(void) { #if defined HAVE_SLOPPY_STRUCTS_INIT static const struct grep_atom_s res = {0}; #else static const struct grep_atom_s res; #endif /* HAVE_SLOPPY_STRUCTS_INIT */ return res; } static inline __attribute__((pure, const)) struct grep_atom_soa_s __grep_atom_soa_initialiser(void) { #if defined HAVE_SLOPPY_STRUCTS_INIT static const struct grep_atom_soa_s res = {0}; #else static const struct grep_atom_soa_s res; #endif /* HAVE_SLOPPY_STRUCTS_INIT */ return res; } static inline struct grep_atom_soa_s make_grep_atom_soa(grep_atom_t atoms, size_t natoms) { struct grep_atom_soa_s res = __grep_atom_soa_initialiser(); res.needle = (char*)atoms; res.flesh = (void*)(res.needle + natoms); return res; } #define GRPATM_NEEDLELESS_MODE_CHAR (1) /* formatter */ static inline size_t dt_io_strfdt( char *restrict buf, size_t bsz, const char *fmt, struct dt_dt_s that, int apnd_ch) { size_t res = dt_strfdt(buf, bsz, fmt, that); if (LIKELY(res > 0) && apnd_ch && buf[res - 1] != apnd_ch) { /* auto-newline */ buf[res++] = (char)apnd_ch; } return res; } static __attribute__((unused)) size_t __io_write(const char *line, size_t llen, FILE *where) { #if defined __GLIBC__ return fwrite_unlocked(line, sizeof(*line), llen, where); #else /* !__GLIBC__ */ return fwrite(line, sizeof(*line), llen, where); #endif /* __GLIBC__ */ } static __attribute__((unused)) int __io_putc(int c, FILE *where) { #if defined __GLIBC__ return fputc_unlocked(c, where); #else /* !__GLIBC__ */ return fputc(c, where); #endif /* __GLIBC__ */ } static inline __attribute__((unused)) void #if defined __GLIBC__ __io_setlocking_bycaller(FILE *fp) { __fsetlocking(fp, FSETLOCKING_BYCALLER); return; } #else /* !__GLIBC__ */ __io_setlocking_bycaller(__attribute__((unused)) FILE *fp) { return; } #endif /* __GLIBC__ */ static inline __attribute__((unused)) int __io_eof_p(FILE *fp) { #if defined __GLIBC__ return feof_unlocked(fp); #else /* !__GLIBC__ */ return feof(fp); #endif /* __GLIBC__ */ } static inline void dt_io_warn_strpdt(const char *inp) { error("cannot make sense of `%s' using the given input formats", inp); return; } /* duration parser */ static inline __attribute__((pure, const)) struct __strpdtdur_st_s __strpdtdur_st_initialiser(void) { #if defined HAVE_SLOPPY_STRUCTS_INIT static const struct __strpdtdur_st_s res = {}; #else static const struct __strpdtdur_st_s res; #endif /* HAVE_SLOPPY_STRUCTS_INIT */ return res; } static inline int __strpdtdur_more_p(struct __strpdtdur_st_s *st) { return st->cont != NULL; } static inline void __strpdtdur_free(struct __strpdtdur_st_s *st) { if (st->durs != NULL) { free(st->durs); } return; } #endif /* INCLUDED_dt_io_h_ */ dateutils-0.4.5/src/dtest.c000066400000000000000000000074641335042257000156100ustar00rootroot00000000000000/*** dtest.c -- like test(1) but for dates * * Copyright (C) 2011-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of dateutils. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * **/ #if defined HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #include "dt-core.h" #include "dt-io.h" #include "dt-locale.h" const char *prog = "dtest"; #include "dtest.yucc" int main(int argc, char *argv[]) { yuck_t argi[1U]; char **ifmt; size_t nifmt; struct dt_dt_s d1, d2; zif_t fromz = NULL; int res = 0; if (yuck_parse(argi, argc, argv)) { res = 2; goto out; } if (argi->nargs != 1U + !argi->isvalid_flag) { yuck_auto_help(argi); res = 2; goto out; } if (argi->from_locale_arg) { setilocale(argi->from_locale_arg); } if (argi->from_zone_arg) { fromz = dt_io_zone(argi->from_zone_arg); } if (argi->base_arg) { struct dt_dt_s base = dt_strpdt(argi->base_arg, NULL, NULL); dt_set_base(base); } ifmt = argi->input_format_args; nifmt = argi->input_format_nargs; if (argi->isvalid_flag) { /* check that one date */ res = dt_unk_p(dt_io_strpdt(*argi->args, ifmt, nifmt, fromz)); goto out; } if (dt_unk_p(d1 = dt_io_strpdt(argi->args[0U], ifmt, nifmt, fromz))) { if (!argi->quiet_flag) { dt_io_warn_strpdt(argi->args[0U]); } res = 2; goto out; } if (dt_unk_p(d2 = dt_io_strpdt(argi->args[1U], ifmt, nifmt, fromz))) { if (!argi->quiet_flag) { dt_io_warn_strpdt(argi->args[1U]); } res = 2; goto out; } /* just do the comparison */ if ((res = dt_dtcmp(d1, d2)) == -2) { /* uncomparable */ res = 3; } else if (argi->cmp_flag) { switch (res) { case 0: res = 0; break; case -1: res = 2; break; case 1: res = 1; break; default: res = 3; break; } } else if (argi->eq_flag) { res = res == 0 ? 0 : 1; } else if (argi->ne_flag) { res = res != 0 ? 0 : 1; } else if (argi->lt_flag || argi->ot_flag) { res = res == -1 ? 0 : 1; } else if (argi->le_flag) { res = res == -1 || res == 0 ? 0 : 1; } else if (argi->gt_flag || argi->nt_flag) { res = res == 1 ? 0 : 1; } else if (argi->ge_flag) { res = res == 1 || res == 0 ? 0 : 1; } out: dt_io_clear_zones(); if (argi->from_locale_arg) { setilocale(NULL); } yuck_free(argi); return res; } /* dtest.c ends here */ dateutils-0.4.5/src/dtest.yuck000066400000000000000000000050671335042257000163360ustar00rootroot00000000000000Usage: datetest [OPTION]... DATE/TIME1 OP DATE/TIME2 Like test(1) but for dates. -h, --help Print help and exit -V, --version Print version and exit -q, --quiet Suppress message about date/time and duration parser errors. -i, --input-format=STRING... Input format, can be used multiple times. Each date/time will be passed to the input format parsers in the order they are given, if a date/time can be read successfully with a given input format specifier string, that value will be used. -b, --base=DT For underspecified input use DT as a fallback to fill in missing fields. Also used for ambiguous format specifiers to position their range on the absolute time line. Must be a date/time in ISO8601 format. If omitted defaults to the current date/time. --from-locale=LOCALE Interpret dates on stdin or the command line as coming from the locale LOCALE, this would only affect month and weekday names as input formats have to be specified explicitly. --from-zone=ZONE Interpret dates on stdin or the command line as coming from the time zone ZONE. -e, --backslash-escapes Enable interpretation of backslash escapes in the output and input format specifier strings. --eq DATE/TIME1 is the same as DATE/TIME2 --ne DATE/TIME1 is not the same as DATE/TIME2 --gt DATE/TIME1 is newer than DATE/TIME2 --lt DATE/TIME1 is older than DATE/TIME2 --ge DATE/TIME1 is newer than or equals DATE/TIME2 --le DATE/TIME1 is older than or equals DATE/TIME2 --nt DATE/TIME1 is newer than DATE/TIME2 --ot DATE/TIME1 is older than DATE/TIME2 --cmp compare DATE/TIME1 to DATE/TIME2, return with 0 if equal, 1 if left argument was newer and 2 if right argument was newer --isvalid Return success if dates specified conform to input format. dateutils-0.4.5/src/dzone.c000066400000000000000000000213211335042257000155700ustar00rootroot00000000000000/*** dzone.c -- convert date/times between timezones * * Copyright (C) 2011-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of dateutils. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * **/ #if defined HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include "dt-core.h" #include "dt-io.h" #include "dt-core-tz-glue.h" #include "dt-locale.h" #include "tzraw.h" struct ztr_s { int32_t trns; int32_t offs; }; /* fwd decld in tzraw.h */ struct ztrdtl_s { int32_t offs; uint8_t dstp; uint8_t abbr; } __attribute__((packed)); const char *prog = "dzone"; static char gbuf[256U]; static const char never[] = "never"; static const char nindi[] = " -> "; static const char pindi[] = " <- "; static size_t xstrlcpy(char *restrict dst, const char *src, size_t dsz) { size_t ssz = strlen(src); if (ssz > dsz) { ssz = dsz - 1U; } memcpy(dst, src, ssz); dst[ssz] = '\0'; return ssz; } static struct dt_dt_s dz_enrichz(struct dt_dt_s d, zif_t zone) { /* like dtz_enrichz() but with fix-up for date-only dt's */ struct dt_dt_s x = d; if (UNLIKELY(zone == NULL)) { goto out; } else if (d.typ == DT_SEXY) { goto out; } else if (dt_sandwich_only_d_p(d)) { static struct dt_t_s mid = {.hms = {.h = 24}}; dt_make_sandwich(&x, d.d.typ, DT_HMS); x.t = mid; } x = dtz_enrichz(x, zone); if (dt_sandwich_only_d_p(d)) { /* keep .zdiff and .neg */ d.neg = x.neg; d.zdiff = x.zdiff; x = d; } out: return x; } static int dz_io_write(struct dt_dt_s d, zif_t zone, const char *name) { static const char fmt[] = "%FT%T%Z\0%F%Z"; char *restrict bp = gbuf; const char *const ep = gbuf + sizeof(gbuf); size_t fof = 0U; /* pick a format */ fof += dt_sandwich_only_t_p(d) * 3U; fof += dt_sandwich_only_d_p(d) * 8U; /* let's go */ d = dz_enrichz(d, zone); bp += dt_strfdt(bp, ep - bp, fmt + fof, d); /* append name */ if (LIKELY(name != NULL)) { *bp++ = '\t'; bp += xstrlcpy(bp, name, ep - bp); } *bp++ = '\n'; __io_write(gbuf, bp - gbuf, stdout); return (bp > gbuf) - 1; } static size_t dz_strftr(char *restrict buf, size_t bsz, struct ztr_s t) { static const char fmt[] = "%FT%T%Z"; struct dt_dt_s d = dt_dt_initialiser(); d.typ = DT_SEXY; d.sexy = t.trns + t.offs; if (t.offs > 0) { d.zdiff = (uint16_t)(t.offs / ZDIFF_RES); } else if (t.offs < 0) { d.neg = 1; d.zdiff = (uint16_t)(-t.offs / ZDIFF_RES); } return dt_strfdt(buf, bsz, fmt, d); } static int dz_write_nxtr(struct zrng_s r, zif_t z, const char *zn) { char *restrict bp = gbuf; const char *const ep = gbuf + sizeof(gbuf); size_t ntr = zif_ntrans(z); if (r.next == INT_MAX) { bp += xstrlcpy(bp, never, bp - ep); } else { bp += dz_strftr(bp, ep - bp, (struct ztr_s){r.next, r.offs}); } /* append next indicator */ bp += xstrlcpy(bp, nindi, bp - ep); if (r.trno + 1U < ntr) { /* thank god there's another one */ struct ztrdtl_s zd = zif_trdtl(z, r.trno + 1); if (r.next == INT_MAX) { goto never; } bp += dz_strftr(bp, ep - bp, (struct ztr_s){r.next, zd.offs}); } else { never: bp += xstrlcpy(bp, never, bp - ep); } /* append name */ if (LIKELY(zn != NULL)) { *bp++ = '\t'; bp += xstrlcpy(bp, zn, ep - bp); } *bp++ = '\n'; __io_write(gbuf, bp - gbuf, stdout); return (bp > gbuf) - 1; } static int dz_write_prtr(struct zrng_s r, zif_t UNUSED(z), const char *zn) { char *restrict bp = gbuf; const char *const ep = gbuf + sizeof(gbuf); if (r.trno >= 1) { /* there's one before that */ struct ztrdtl_s zd = zif_trdtl(z, r.trno - 1); bp += dz_strftr(bp, ep - bp, (struct ztr_s){r.prev, zd.offs}); } else { bp += xstrlcpy(bp, never, bp - ep); } /* append prev indicator */ bp += xstrlcpy(bp, pindi, bp - ep); if (r.prev == INT_MIN) { bp += xstrlcpy(bp, never, bp - ep); } else { bp += dz_strftr(bp, ep - bp, (struct ztr_s){r.prev, r.offs}); } /* append name */ if (LIKELY(zn != NULL)) { *bp++ = '\t'; bp += xstrlcpy(bp, zn, ep - bp); } *bp++ = '\n'; __io_write(gbuf, bp - gbuf, stdout); return (bp > gbuf) - 1; } #include "dzone.yucc" int main(int argc, char *argv[]) { yuck_t argi[1U]; int rc = 0; zif_t fromz = NULL; char **fmt; size_t nfmt; /* all them zones to consider */ struct { zif_t zone; const char *name; } *z = NULL; size_t nz = 0U; /* all them datetimes to consider */ struct dt_dt_s *d = NULL; size_t nd = 0U; bool trnsp = false; if (yuck_parse(argi, argc, argv)) { rc = 1; goto out; } else if (argi->nargs == 0U) { error("Need at least a ZONENAME or a DATE/TIME"); rc = 1; goto out; } if (argi->from_locale_arg) { setilocale(argi->from_locale_arg); } /* try and read the from and to time zones */ if (argi->from_zone_arg) { fromz = dt_io_zone(argi->from_zone_arg); } if (argi->next_flag || argi->prev_flag) { trnsp = true; } if (argi->base_arg) { struct dt_dt_s base = dt_strpdt(argi->base_arg, NULL, NULL); dt_set_base(base); } /* very well then */ fmt = argi->input_format_args; nfmt = argi->input_format_nargs; /* initially size the two beef arrays as large as there is input * we'll then sort them by traversing the input args and ass'ing * to the one or the other */ nz = 0U; if (UNLIKELY((z = malloc(argi->nargs * sizeof(*z))) == NULL)) { error("failed to allocate space for zone info"); goto out; } nd = 0U; if (UNLIKELY((d = malloc(argi->nargs * sizeof(*d))) == NULL)) { error("failed to allocate space for date/times"); goto out; } for (size_t i = 0U; i < argi->nargs; i++) { const char *inp = argi->args[i]; /* try dt_strp'ing the input or assume it's a zone */ if (!dt_unk_p(d[nd] = dt_io_strpdt(inp, fmt, nfmt, fromz))) { if (UNLIKELY(d[nd].fix) && !argi->quiet_flag) { rc = 2; } nd++; } else if ((z[nz].zone = dt_io_zone(inp)) != NULL) { z[nz].name = inp; nz++; } else if (!argi->quiet_flag) { /* just bollocks */ error("\ Cannot use `%s', it does not appear to be a zonename\n\ nor a date/time corresponding to the given input formats", inp); rc = 2; } } /* operate with default zone UTC and default time now */ if (nz == 0U) { z[nz].zone = NULL; z[nz].name = NULL; nz++; } if (nd == 0U && !trnsp) { d[nd++] = dt_datetime((dt_dttyp_t)DT_YMD); } else if (nd == 0U) { d[nd++] = dt_datetime((dt_dttyp_t)DT_SEXY); } /* just go through them all now */ if (LIKELY(!trnsp)) { for (size_t i = 0U; !trnsp && i < nd; i++) { for (size_t j = 0U; j < nz; j++) { dz_io_write(d[i], z[j].zone, z[j].name); } } } else { /* otherwise traverse the zones and determine transitions */ for (size_t i = 0U; i < nd; i++) { struct dt_dt_s di = dt_dtconv(DT_SEXY, d[i]); for (size_t j = 0U; j < nz; j++) { const zif_t zj = z[j].zone; const char *zn = z[j].name; struct zrng_s r; if (UNLIKELY(zj == NULL)) { /* don't bother */ continue; } /* otherwise find the range */ r = zif_find_zrng(zj, di.sexy); if (argi->next_flag) { dz_write_nxtr(r, zj, zn); } if (argi->prev_flag) { dz_write_prtr(r, zj, zn); } } } } out: /* release the zones */ dt_io_clear_zones(); /* release those arrays */ if (LIKELY(z != NULL)) { free(z); } if (LIKELY(d != NULL)) { free(d); } if (argi->from_locale_arg) { setilocale(NULL); } yuck_free(argi); return rc; } /* dzone.c ends here */ dateutils-0.4.5/src/dzone.yuck000066400000000000000000000046361335042257000163330ustar00rootroot00000000000000Usage: datezone [OPTION]... [ZONENAME]... [DATE/TIME]... Convert DATE/TIMEs between timezones. If DATE/TIME is omitted, it defaults to `now'. DATE/TIME can also be one of the following specials - `now' interpreted as the current (UTC) time stamp - `time' the time part of the current (UTC) time stamp - `today' the current date (according to UTC) - `tomo[rrow]' tomorrow's date (according to UTC) - `y[ester]day' yesterday's date (according to UTC) When DATE/TIME is a date (i.e. the time component is omitted) the result will show the timezone offset at the end of that day. When DATE/TIME is a time (i.e. the date component is omitted) the conversion takes place on the date as specified by --base|-b, by default the current date. -q, --quiet Suppress message about date/time or zonename parser errors and fix-ups. The default is to print a warning or the fixed up value and return error code 2. -b, --base=DT For underspecified input use DT as a fallback to fill in missing fields. Also used for ambiguous format specifiers to position their range on the absolute time line. Must be a date/time in ISO8601 format. If omitted defaults to the current date/time. -i, --input-format=STRING... Input format, can be used multiple times. Each date/time will be passed to the input format parsers in the order they are given, if a date/time can be read successfully with a given input format specifier string, that value will be used. --from-locale=LOCALE Interpret dates on stdin or the command line as coming from the locale LOCALE, this would only affect month and weekday names as input formats have to be specified explicitly. --from-zone=ZONE Interpret dates on stdin or the command line as coming from the time zone ZONE. --next Show next transition from/to DST. --prev Show previous transition from/to DST. dateutils-0.4.5/src/prchunk.c000066400000000000000000000264261335042257000161360ustar00rootroot00000000000000/*** prchunk.c -- guessing line oriented data formats * * Copyright (C) 2010-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of uterus. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***/ #define PRCHUNK_C #if defined HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #if defined MAP_ANON_NEEDS_DARWIN_SOURCE # define _DARWIN_C_SOURCE #endif /* MAP_ANON_NEEDS_DARWIN_SOURCE */ #if defined MAP_ANON_NEEDS_ALL_SOURCE # define _ALL_SOURCE #endif /* MAP_ANON_NEEDS_ALL_SOURCE */ #include #include #include #include #include #include #include #include #include #include #include "nifty.h" #include "prchunk.h" #define MAX_NLINES (16384) #define MAX_LLEN (1024) #if !defined MAP_ANONYMOUS && defined MAP_ANON # define MAP_ANONYMOUS (MAP_ANON) #elif !defined MAP_ANON # define MAP_ANON (0x1000U) #endif /* MAP_ANON->MAP_ANONYMOUS */ #if defined __INTEL_COMPILER # pragma warning(disable: 981) #endif /* __INTEL_COMPILER */ typedef uint32_t off32_t; typedef uint16_t off16_t; struct prch_ctx_s { /* file descriptor */ int fd; /* buffer */ char *buf; /* number of lines in the buffer */ uint32_t tot_lno; /* number of columns per line */ uint32_t tot_cno; /* number of bytes in the buffer */ size_t bno; /* last known offset */ size_t off; /* offsets */ off32_t loff[MAX_NLINES]; off32_t cur_lno; /* delimiter offsets */ off16_t *soff; }; /* error() impl */ static void __attribute__((format(printf, 2, 3))) error(int eno, const char *fmt, ...) { va_list vap; va_start(vap, fmt); fputs("prchunk: ", stderr); vfprintf(stderr, fmt, vap); va_end(vap); if (eno) { fputc(':', stderr); fputc(' ', stderr); fputs(strerror(eno), stderr); } fputc('\n', stderr); return; } static inline void set_loff(prch_ctx_t ctx, uint32_t lno, off32_t off) { ctx->loff[lno] = off; ctx->loff[lno] <<= 1; return; } static inline off32_t get_loff(prch_ctx_t ctx, uint32_t lno) { off32_t res = ctx->loff[lno]; return res >> 1; } /* return 0 if not \r terminated, 1 otherwise */ static inline int lftermdp(prch_ctx_t ctx, uint32_t lno) { return ctx->loff[lno] & 1; } static inline void set_lftermd(prch_ctx_t ctx, uint32_t lno) { ctx->loff[lno] |= 1; return; } static inline size_t get_llen(prch_ctx_t ctx, uint32_t lno) { if (UNLIKELY(lno == 0)) { return get_loff(ctx, 0) - lftermdp(ctx, 0); } return get_loff(ctx, lno) - lftermdp(ctx, lno) - get_loff(ctx, lno - 1) - 1; } /* internal operations */ FDEFU int prchunk_fill(prch_ctx_t ctx) { /* this is a coroutine consisting of a line counter yielding the number of * lines read so far and a reader yielding a buffer fill and the number of * bytes read */ #define CHUNK_SIZE (4096) #define YIELD(x) goto yield##x char *off = ctx->buf + 0; char *bno = ctx->buf + ctx->bno; ssize_t nrd; /* initial work, reset the line counters et al */ ctx->tot_lno = 0; /* we just memcpy() the left over stuff to the front and restart * from there, someone left us a note in __ctx with the left * over offset */ /* normally we'd use memmove() but we know there's little chance * for overlapping regions */ if (UNLIKELY(ctx->bno == 0)) { /* do nothing */ ; } else if (LIKELY(ctx->bno > ctx->off)) { size_t rsz = ctx->bno - ctx->off; /* move the top RSZ bytes to the beginning */ memcpy(ctx->buf, ctx->buf + ctx->off, rsz); ctx->bno = rsz; bno = ctx->buf + rsz; } else if (UNLIKELY(ctx->bno == ctx->off)) { /* what are the odds? just reset the counters */ ctx->bno = 0; bno = ctx->buf; } else { /* the user didn't see the end of the file */ return -1; } yield1: /* read CHUNK_SIZE bytes */ bno += (nrd = read(ctx->fd, bno, CHUNK_SIZE)); /* if we came from yield2 then off == __ctx->bno, and if we * read 0 or less bytes then off >= __ctx->bno + nrd, so we * can simply use that compact expression if the buffer has no * more input. * On the contrary if we came from the outside, i.e. fill_buffer() * has been called, then off would be 0 and __ctx->bno would be * the buffer filled so far, if no more bytes could be read then * we'd proceed processing them (off < __ctx->bno + nrd */ if (UNLIKELY(!nrd && off < bno && ctx->cur_lno <= ctx->tot_lno)) { /* last line then, unyielded :| */ set_loff(ctx, 0, bno - ctx->buf); YIELD(4); } else if (UNLIKELY(nrd <= 0 && off == ctx->buf)) { /* special case, we worked our arses off and nothing's * in the pipe line so just fuck off here */ return -1; } else if (LIKELY(off < bno || off == ctx->buf)) { YIELD(2); } /* proceed to exit */ YIELD(3); yield2: while (off < bno) { size_t rsz = bno - off; char *p = memchr(off, '\n', rsz); if (UNLIKELY(p == NULL)) { if (LIKELY(nrd > 0)) { break; } /* fucking idiots didnt conclude with a \n */ error(0, "ID:10T error"); p = bno; } /* massage our status structures */ set_loff(ctx, ctx->tot_lno, p - ctx->buf); if (UNLIKELY(p[-1] == '\r')) { /* oh god, when is this nightmare gonna end */ p[-1] = '\0'; set_lftermd(ctx, ctx->tot_lno); } *p = '\0'; off = ++p; /* count it as line and check if we need more */ if (++ctx->tot_lno >= MAX_NLINES) { YIELD(3); } } YIELD(1); yield3: /* need clean up, something like unread(), * in particular leave a note in __ctx with the left over offset */ ctx->cur_lno = 0; yield4: ctx->off = off - ctx->buf; ctx->bno = bno - ctx->buf; #undef YIELD #undef CHUNK_SIZE return 0; } /* public operations */ FDEFU prch_ctx_t init_prchunk(int fd) { #define MAP_MEM (MAP_ANON | MAP_PRIVATE) #define PROT_MEM (PROT_READ | PROT_WRITE) #define MAP_LEN (MAX_NLINES * MAX_LLEN) static struct prch_ctx_s __ctx; __ctx.buf = mmap(NULL, MAP_LEN, PROT_MEM, MAP_MEM, -1, 0); if (__ctx.buf == MAP_FAILED) { return NULL; } /* bit of space for the rechunker */ __ctx.soff = mmap(NULL, MAP_LEN, PROT_MEM, MAP_MEM, -1, 0); if (__ctx.soff == MAP_FAILED) { return NULL; } if ((__ctx.fd = fd) > STDIN_FILENO) { #if defined POSIX_FADV_SEQUENTIAL /* give advice about our read pattern */ int rc = posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL); if (UNLIKELY(rc < 0)) { munmap(__ctx.soff, MAP_LEN); return NULL; } #endif /* POSIX_FADV_SEQUENTIAL */ } return &__ctx; } FDEFU void free_prchunk(prch_ctx_t ctx) { if (LIKELY(ctx->buf != NULL)) { munmap(ctx->buf, MAP_LEN); ctx->buf = NULL; } return; } /* accessors/iterators/et al. */ FDEFU size_t prchunk_get_nlines(prch_ctx_t ctx) { return ctx->tot_lno; } FDEFU size_t prchunk_getlineno(prch_ctx_t ctx, char **p, int lno) { if (UNLIKELY(lno <= 0)) { *p = ctx->buf; return get_llen(ctx, 0); } else if (UNLIKELY((size_t)lno >= prchunk_get_nlines(ctx))) { *p = NULL; return 0; } /* likely case last, what bollocks */ *p = ctx->buf + get_loff(ctx, lno - 1) + 1; return get_llen(ctx, lno); } FDEFU size_t prchunk_getline(prch_ctx_t ctx, char **p) { return prchunk_getlineno(ctx, p, ctx->cur_lno++); } FDEFU void prchunk_reset(prch_ctx_t ctx) { ctx->cur_lno = 0; return; } FDEFU int prchunk_haslinep(prch_ctx_t ctx) { /* the second condition is to allow unterminated last lines */ return ctx->cur_lno < ctx->tot_lno || ctx->cur_lno == 0U; } static inline void set_ncols(prch_ctx_t ctx, size_t ncols) { ctx->tot_cno = ncols; return; } FDEFU size_t prchunk_get_ncols(prch_ctx_t ctx) { return ctx->tot_cno; } static inline void set_col_off(prch_ctx_t ctx, size_t lno, size_t cno, size_t off) { ctx->soff[lno * prchunk_get_ncols(ctx) + cno] = (off16_t)off; return; } static inline off16_t get_col_off(prch_ctx_t ctx, size_t lno, size_t cno) { return ctx->soff[lno * prchunk_get_ncols(ctx) + cno]; } /* rechunker, chop the lines into smaller bits * Strategy is to go over all lines in the current chunk and * memchr() for the delimiter DELIM. * Store the offsets into __ctx->soff and bugger off leaving a \0 * where the delimiter was. */ FDEFU void prchunk_rechunk(prch_ctx_t ctx, char dlm, int ncols) { /* very naive implementation, we prefer prchunk_rechunk_by_dstfld() * where a distance histogram demarks possible places */ size_t lno = 0; size_t cno = 0; char *line; char *off; char *p; char *bno = ctx->buf + ctx->off; size_t rsz; set_ncols(ctx, ncols); off = line = ctx->buf; rsz = bno - off; while ((p = memchr(off, dlm, rsz)) != NULL) { size_t co; size_t llen = get_llen(ctx, lno); while ((co = p - line) > llen) { /* last column offset equals the length of the line */ set_col_off(ctx, lno, cno, llen); /* get the new line */ line = ctx->buf + get_loff(ctx, lno++) + 1; cno = 0; } /* store the offset of the column within the line */ set_col_off(ctx, lno, cno++, co); /* prepare the counters for the next round */ *p = '\0'; off = ++p; rsz = bno - off; } /* last column offset equals the length of the line */ rsz = get_llen(ctx, lno); set_col_off(ctx, lno, cno, rsz); return; } FDEFU size_t prchunk_getcolno(prch_ctx_t ctx, char **p, int lno, int cno) { size_t co1, co2; if (UNLIKELY(cno < 0 || (size_t)cno >= prchunk_get_ncols(ctx))) { *p = NULL; return 0; } (void)prchunk_getlineno(ctx, p, lno); if (UNLIKELY(cno == 0)) { return get_col_off(ctx, lno, 0); } /* likely case last */ co1 = get_col_off(ctx, lno, cno); co2 = get_col_off(ctx, lno, cno - 1); *p += co2 + 1; return co1 - co2 - 1; } #if defined STANDALONE int main(int argc, char *argv[]) { int fd; prch_ctx_t ctx; if (argc <= 1) { fd = STDIN_FILENO; } else if ((fd = open(argv[1], O_RDONLY)) < 0) { return 1; } /* get our prchunk up n running */ if ((ctx = init_prchunk(fd)) == NULL) { error(errno, "Error: ctx NULL"); return 1; } /* fill the buffer */ while (!(prchunk_fill(ctx) < 0)) { char *l[1]; size_t llen; int i = 0; while ((llen = prchunk_getline(ctx, l))) { fprintf(stderr, "%d (%zu) %s\n", i++, llen, l[0]); } } /* and out */ free_prchunk(ctx); close(fd); return 0; } #endif /* STANDALONE */ /* prchunk.c ends here */ dateutils-0.4.5/src/prchunk.h000066400000000000000000000047721335042257000161430ustar00rootroot00000000000000/*** prchunk.h -- guessing line oriented data formats * * Copyright (C) 2010-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of uterus. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***/ #if !defined INCLUDED_prchunk_h_ #define INCLUDED_prchunk_h_ #if !defined STATIC_GUTS # define FDECL extern # define FDEFU #else /* STATIC_GUTS */ # define FDECL static # define FDEFU static #endif /* !STATIC_GUTS */ typedef struct prch_ctx_s *prch_ctx_t; /* non-reentrant! */ FDECL prch_ctx_t init_prchunk(int fd); FDECL void free_prchunk(prch_ctx_t); FDECL int prchunk_fill(prch_ctx_t ctx); FDECL size_t prchunk_get_nlines(prch_ctx_t); FDECL size_t prchunk_get_ncols(prch_ctx_t); FDECL size_t prchunk_getlineno(prch_ctx_t ctx, char **p, int lno); FDECL size_t prchunk_getline(prch_ctx_t ctx, char **p); FDECL void prchunk_reset(prch_ctx_t ctx); FDECL int prchunk_haslinep(prch_ctx_t ctx); FDECL void prchunk_rechunk(prch_ctx_t ctx, char delim, int ncols); FDECL size_t prchunk_getcolno(prch_ctx_t ctx, char **p, int lno, int cno); #endif /* INCLUDED_prchunk_h_ */ dateutils-0.4.5/src/strpdt-special.gperf000066400000000000000000000007101335042257000202670ustar00rootroot00000000000000%{ %} %7bit %readonly-tables %switch=1 %ignore-case %enum %struct-type %define slot-name special %define hash-function-name ____strpdt_special %define lookup-function-name __strpdt_special %null-strings struct dt_strpdt_special_s { const char *special; dt_strpdt_special_t e; }; %% now, STRPDT_NOW today, STRPDT_DATE date, STRPDT_DATE tomo, STRPDT_TOMO tomorrow, STRPDT_TOMO yday, STRPDT_YDAY yest, STRPDT_YDAY yesterday, STRPDT_YDAY time, STRPDT_TIME dateutils-0.4.5/src/strptime.c000066400000000000000000000115361335042257000163270ustar00rootroot00000000000000/*** strptime.c -- a shell interface to strptime(3) * * Copyright (C) 2011-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of dateutils. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***/ #if defined HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #include #include #include "dt-io.h" #include "prchunk.h" const char *prog = "strptime"; static int pars_line(struct tm *tm, const char *const *fmt, size_t nfmt, const char *line) { for (size_t i = 0; i < nfmt; i++) { if (fmt[i] && strptime(line, fmt[i], tm) != NULL) { return 0; } } return -1; } static void prnt_line(const char *ofmt, struct tm *tm) { char res[256]; strftime(res, sizeof(res), ofmt, tm); fputs(res, stdout); return; } static inline __attribute__((pure, const)) struct tm __tm_initialiser(void) { #if defined HAVE_SLOPPY_STRUCTS_INIT static const struct tm res = {}; #else static const struct tm res; #endif /* HAVE_SLOPPY_STRUCTS_INIT */ return res; } static void proc_line( const char *ln, const char *const *fmt, size_t nfmt, const char *ofmt, int quietp) { struct tm tm = __tm_initialiser(); if (pars_line(&tm, fmt, nfmt, ln) < 0) { if (!quietp) { dt_io_warn_strpdt(ln); } } else { prnt_line(ofmt, &tm); } return; } static void proc_lines(const char *const *fmt, size_t nfmt, const char *ofmt, int quietp) { size_t lno = 0; void *pctx; /* using the prchunk reader now */ if ((pctx = init_prchunk(STDIN_FILENO)) == NULL) { serror("Error: could not open stdin"); return; } while (prchunk_fill(pctx) >= 0) { for (char *line; prchunk_haslinep(pctx); lno++) { (void)prchunk_getline(pctx, &line); /* check if line matches */ proc_line(line, fmt, nfmt, ofmt, quietp); } } /* get rid of resources */ free_prchunk(pctx); return; } #include "strptime.yucc" int main(int argc, char *argv[]) { static char dflt_fmt[] = "%Y-%m-%d\n\0H:%M:%S %Z\n"; yuck_t argi[1U]; char *outfmt = dflt_fmt; char **infmt; size_t ninfmt; char **input; size_t ninput; int quietp; int res = 0; if (yuck_parse(argi, argc, argv)) { res = 1; goto out; } if (argi->format_arg) { outfmt = argi->format_arg; /* unescape sequences, maybe */ if (argi->backslash_escapes_flag) { dt_io_unescape(outfmt); } } else if (argi->time_flag) { outfmt[8] = ' '; outfmt[9] = '%'; } if (!argi->input_format_nargs) { infmt = argi->args; ninfmt = argi->nargs; input = NULL; ninput = 0; } else { infmt = argi->input_format_args; ninfmt = argi->input_format_nargs; input = argi->args; ninput = argi->nargs; } /* get quiet predicate */ quietp = argi->quiet_flag; /* set locale specific/independent behaviour */ with (const char *loc) { if (!argi->locale_flag) { loc = "C"; /* we need to null out TZ for UTC */ setenv("TZ", "", 1); } else { loc = ""; } /* actually set our findings in stone */ setlocale(LC_TIME, loc); tzset(); } /* get lines one by one, apply format string and print date/time */ if (ninput == 0) { /* read from stdin */ proc_lines((const char*const*)infmt, ninfmt, outfmt, quietp); } else { const char *const *cinfmt = (const char*const*)infmt; for (size_t i = 0; i < ninput; i++) { proc_line(input[i], cinfmt, ninfmt, outfmt, quietp); } } out: yuck_free(argi); return res; } /* strptime.c ends here */ dateutils-0.4.5/src/strptime.yuck000066400000000000000000000033271335042257000170570ustar00rootroot00000000000000Usage: strptime [OPTION]... [INPUT]... Parse input from stdin according to one of the given formats FORMATs. The format string specifiers are the same as for strptime(3). -h, --help Print help and exit -V, --version Print version and exit -t, --time also display time in the output, default is to display the date -q, --quiet Suppress message about date/time and duration parser errors. -f, --format=STRING Output format. This can either be a specifier string (similar to strftime()'s FMT) or the name of a calendar. -i, --input-format=STRING... Input format, can be used multiple times. Each date/time will be passed to the input format parsers in the order they are given, if a date/time can be read successfully with a given input format specifier string, that value will be used. -e, --backslash-escapes Enable interpretation of backslash escapes in the output and input format specifier strings. -S, --sed-mode Copy parts from the input before and after a matching date/time. Note that all occurrences of date/times within a line will be processed. -l, --locale Make internal strptime(3) and strftime(3) behave in a locale dependent way, default is to pretend LC_ALL=C is in place. dateutils-0.4.5/test/000077500000000000000000000000001335042257000144765ustar00rootroot00000000000000dateutils-0.4.5/test/Makefile.am000066400000000000000000000633241335042257000165420ustar00rootroot00000000000000# Help the Developers and yourself. Just use the C locale and settings # for the compilation. They can still be overriden by make LANG= # but that is general a not very good idea include $(top_builddir)/version.mk LANG = C LC_ALL = C libdir = $(abs_top_srcdir)/lib AM_CPPFLAGS = -D_POSIX_C_SOURCE=200112L -D_XOPEN_SOURCE=600 -D_BSD_SOURCE AM_CPPFLAGS += -DTEST -I"$(libdir)" -I"$(abs_top_builddir)/lib" EXTRA_DIST = EXTRA_DIST += $(dt_tests) EXTRA_DIST += $(batch_tests) EXTRA_DIST += $(built_dist_sources) TESTS = $(bin_tests) $(dt_tests) $(batch_tests) TESTS_ENVIRONMENT = TEST_EXTENSIONS = BUILT_SOURCES = $(built_dist_sources) $(built_nodist_sources) built_dist_sources = built_nodist_sources = dt_tests = bin_tests = batch_tests = check_PROGRAMS = CLEANFILES = $(check_PROGRAMS) DISTCLEANFILES = $(built_nodist_sources) SUFFIXES = DT_LIBS = $(top_builddir)/lib/libdut.a ## our friendly helper include clitosis.am AM_CLIT_LOG_FLAGS = -v --builddir "$(top_builddir)/src" --timeout 300 --keep-going TESTS_ENVIRONMENT += GPERF=$(GPERF) TESTS_ENVIRONMENT += GDATE=$(GDATE) TESTS_ENVIRONMENT += have_gdate="$(have_gdate)" dt_tests += dseq.01.clit dt_tests += dseq.02.clit dt_tests += dseq.03.clit dt_tests += dseq.04.clit dt_tests += dseq.05.clit dt_tests += dseq.06.clit dt_tests += dseq.07.clit dt_tests += dseq.08.clit dt_tests += dseq.09.clit dt_tests += dseq.10.clit dt_tests += dseq.11.clit dt_tests += dseq.12.clit dt_tests += dseq.13.clit dt_tests += dseq.14.clit dt_tests += dseq.15.clit dt_tests += dseq.16.clit dt_tests += dseq.17.clit dt_tests += dseq.18.clit dt_tests += dseq.19.clit dt_tests += dseq.20.clit dt_tests += dseq.21.clit dt_tests += dseq.22.clit dt_tests += dseq.23.clit dt_tests += dseq.24.clit dt_tests += dseq.25.clit dt_tests += dseq.26.clit dt_tests += dseq.27.clit dt_tests += dseq.28.clit dt_tests += dseq.29.clit dt_tests += dseq.30.clit dt_tests += dseq.31.clit dt_tests += dseq.32.clit dt_tests += dseq.33.clit dt_tests += dseq.34.clit dt_tests += dseq.35.clit dt_tests += dseq.36.clit dt_tests += dseq.37.clit dt_tests += dseq.38.clit dt_tests += dseq.39.clit dt_tests += dseq.40.clit dt_tests += dseq.41.clit dt_tests += dseq.42.clit dt_tests += dseq.43.clit dt_tests += dseq.44.clit dt_tests += dseq.45.clit dt_tests += dseq.46.clit dt_tests += dseq.47.clit dt_tests += dseq.48.clit dt_tests += dseq.49.clit dt_tests += dseq.50.clit dt_tests += dseq.51.clit dt_tests += dseq.52.clit dt_tests += dseq.53.clit dt_tests += dseq.54.clit dt_tests += dseq.55.clit dt_tests += dseq.56.clit dt_tests += dseq.57.clit dt_tests += dseq.58.clit dt_tests += dseq.59.clit dt_tests += dseq.60.clit dt_tests += dseq.61.clit dt_tests += dconv.001.clit dt_tests += dconv.002.clit dt_tests += dconv.003.clit dt_tests += dconv.004.clit dt_tests += dconv.005.clit dt_tests += dconv.006.clit dt_tests += dconv.007.clit dt_tests += dconv.008.clit dt_tests += dconv.009.clit dt_tests += dconv.010.clit dt_tests += dconv.011.clit dt_tests += dconv.012.clit dt_tests += dconv.013.clit dt_tests += dconv.014.clit dt_tests += dconv.015.clit dt_tests += dconv.016.clit dt_tests += dconv.017.clit dt_tests += dconv.018.clit dt_tests += dconv.019.clit dt_tests += dconv.020.clit dt_tests += dconv.021.clit dt_tests += dconv.022.clit dt_tests += dconv.023.clit dt_tests += dconv.024.clit dt_tests += dconv.025.clit dt_tests += dconv.026.clit dt_tests += dconv.027.clit dt_tests += dconv.028.clit dt_tests += dconv.029.clit dt_tests += dconv.030.clit dt_tests += dconv.031.clit dt_tests += dconv.032.clit dt_tests += dconv.033.clit dt_tests += dconv.034.clit dt_tests += dconv.035.clit dt_tests += dconv.036.clit dt_tests += dconv.037.clit dt_tests += dconv.038.clit dt_tests += dconv.039.clit dt_tests += dconv.040.clit dt_tests += dconv.041.clit dt_tests += dconv.042.clit dt_tests += dconv.043.clit dt_tests += dconv.044.clit dt_tests += dconv.045.clit dt_tests += dconv.046.clit dt_tests += dconv.047.clit dt_tests += dconv.048.clit dt_tests += dconv.049.clit dt_tests += dconv.050.clit dt_tests += dconv.051.clit dt_tests += dconv.052.clit dt_tests += dconv.053.clit dt_tests += dconv.054.clit dt_tests += dconv.055.clit dt_tests += dconv.056.clit dt_tests += dconv.057.clit dt_tests += dconv.058.clit dt_tests += dconv.059.clit dt_tests += dconv.060.clit dt_tests += dconv.061.clit dt_tests += dconv.062.clit dt_tests += dconv.063.clit dt_tests += dconv.064.clit dt_tests += dconv.065.clit dt_tests += dconv.066.clit dt_tests += dconv.067.clit dt_tests += dconv.068.clit dt_tests += dconv.069.clit dt_tests += dconv.070.clit dt_tests += dconv.071.clit dt_tests += dconv.072.clit dt_tests += dconv.073.clit dt_tests += dconv.074.clit dt_tests += dconv.075.clit dt_tests += dconv.076.clit dt_tests += dconv.077.clit dt_tests += dconv.078.clit dt_tests += dconv.079.clit dt_tests += dconv.080.clit dt_tests += dconv.081.clit dt_tests += dconv.082.clit dt_tests += dconv.083.clit dt_tests += dconv.084.clit dt_tests += dconv.085.clit dt_tests += dconv.086.clit dt_tests += dconv.087.clit dt_tests += dconv.088.clit dt_tests += dconv.089.clit dt_tests += dconv.090.clit dt_tests += dconv.091.clit dt_tests += dconv.092.clit dt_tests += dconv.093.clit dt_tests += dconv.094.clit dt_tests += dconv.095.clit dt_tests += dconv.096.clit dt_tests += dconv.097.clit dt_tests += dconv.098.clit dt_tests += dconv.099.clit dt_tests += dconv.100.clit dt_tests += dconv.101.clit dt_tests += dconv.102.clit dt_tests += dconv.103.clit dt_tests += dconv.104.clit dt_tests += dconv.105.clit dt_tests += dconv.106.clit dt_tests += dconv.107.clit dt_tests += dconv.108.clit dt_tests += dconv.109.clit dt_tests += dconv.110.clit dt_tests += dconv.111.clit dt_tests += dconv.112.clit dt_tests += dconv.113.clit dt_tests += dconv.114.clit dt_tests += dconv.115.clit dt_tests += dconv.116.clit dt_tests += dconv.117.clit dt_tests += dconv.118.clit dt_tests += dconv.119.clit dt_tests += dconv.120.clit dt_tests += dconv.121.clit dt_tests += dconv.122.clit dt_tests += dconv.123.clit dt_tests += dconv.124.clit dt_tests += dconv.125.clit dt_tests += dconv.126.clit dt_tests += dconv.127.clit dt_tests += dconv.128.clit dt_tests += dconv.129.clit dt_tests += dconv.130.clit dt_tests += dconv.131.clit dt_tests += dconv.132.clit dt_tests += dconv.133.clit dt_tests += dconv.134.clit dt_tests += dconv.135.clit dt_tests += dconv.136.clit dt_tests += dconv.137.clit dt_tests += dconv.138.clit dt_tests += dadd.001.clit dt_tests += dadd.002.clit dt_tests += dadd.003.clit dt_tests += dadd.004.clit dt_tests += dadd.005.clit dt_tests += dadd.006.clit dt_tests += dadd.007.clit dt_tests += dadd.008.clit dt_tests += dadd.009.clit dt_tests += dadd.010.clit dt_tests += dadd.011.clit dt_tests += dadd.012.clit dt_tests += dadd.013.clit dt_tests += dadd.014.clit dt_tests += dadd.015.clit dt_tests += dadd.016.clit dt_tests += dadd.017.clit dt_tests += dadd.018.clit dt_tests += dadd.019.clit dt_tests += dadd.020.clit dt_tests += dadd.021.clit dt_tests += dadd.022.clit dt_tests += dadd.023.clit dt_tests += dadd.024.clit dt_tests += dadd.025.clit dt_tests += dadd.026.clit dt_tests += dadd.027.clit dt_tests += dadd.028.clit dt_tests += dadd.029.clit dt_tests += dadd.030.clit dt_tests += dadd.031.clit dt_tests += dadd.032.clit dt_tests += dadd.033.clit dt_tests += dadd.034.clit dt_tests += dadd.035.clit dt_tests += dadd.036.clit dt_tests += dadd.037.clit dt_tests += dadd.038.clit dt_tests += dadd.039.clit dt_tests += dadd.040.clit dt_tests += dadd.041.clit dt_tests += dadd.042.clit dt_tests += dadd.043.clit dt_tests += dadd.044.clit dt_tests += dadd.045.clit dt_tests += dadd.046.clit dt_tests += dadd.047.clit dt_tests += dadd.048.clit dt_tests += dadd.049.clit dt_tests += dadd.050.clit dt_tests += dadd.051.clit dt_tests += dadd.052.clit dt_tests += dadd.053.clit dt_tests += dadd.054.clit dt_tests += dadd.055.clit dt_tests += dadd.056.clit dt_tests += dadd.057.clit dt_tests += dadd.058.clit dt_tests += dadd.059.clit dt_tests += dadd.060.clit dt_tests += dadd.061.clit dt_tests += dadd.062.clit dt_tests += dadd.063.clit dt_tests += dadd.064.clit dt_tests += dadd.065.clit dt_tests += dadd.066.clit dt_tests += dadd.067.clit dt_tests += dadd.068.clit dt_tests += dadd.069.clit dt_tests += dadd.070.clit dt_tests += dadd.071.clit dt_tests += dadd.072.clit dt_tests += dadd.073.clit dt_tests += dadd.074.clit dt_tests += dadd.075.clit dt_tests += dadd.076.clit dt_tests += dadd.077.clit dt_tests += dadd.078.clit dt_tests += dadd.079.clit dt_tests += dadd.080.clit dt_tests += dadd.081.clit dt_tests += dadd.082.clit dt_tests += dadd.083.clit dt_tests += dadd.084.clit dt_tests += dadd.085.clit dt_tests += dadd.086.clit dt_tests += dadd.087.clit dt_tests += dadd.088.clit dt_tests += dadd.089.clit dt_tests += dadd.090.clit EXTRA_DIST += dadd.090.dat dt_tests += dadd.091.clit dt_tests += dadd.092.clit dt_tests += dadd.093.clit dt_tests += dadd.094.clit dt_tests += dadd.095.clit dt_tests += dtest.001.clit dt_tests += dtest.002.clit dt_tests += dtest.003.clit dt_tests += dtest.004.clit dt_tests += dtest.005.clit dt_tests += dtest.006.clit dt_tests += dtest.007.clit dt_tests += dtest.008.clit dt_tests += dtest.009.clit dt_tests += dtest.010.clit dt_tests += dtest.011.clit dt_tests += ddiff.001.clit dt_tests += ddiff.002.clit dt_tests += ddiff.003.clit dt_tests += ddiff.004.clit dt_tests += ddiff.005.clit dt_tests += ddiff.006.clit dt_tests += ddiff.007.clit dt_tests += ddiff.008.clit dt_tests += ddiff.009.clit dt_tests += ddiff.010.clit dt_tests += ddiff.011.clit dt_tests += ddiff.012.clit dt_tests += ddiff.013.clit dt_tests += ddiff.014.clit dt_tests += ddiff.015.clit dt_tests += ddiff.016.clit dt_tests += ddiff.017.clit dt_tests += ddiff.018.clit dt_tests += ddiff.019.clit dt_tests += ddiff.020.clit dt_tests += ddiff.021.clit dt_tests += ddiff.022.clit dt_tests += ddiff.023.clit dt_tests += ddiff.024.clit dt_tests += ddiff.025.clit dt_tests += ddiff.026.clit dt_tests += ddiff.027.clit dt_tests += ddiff.028.clit dt_tests += ddiff.029.clit dt_tests += ddiff.030.clit dt_tests += ddiff.031.clit dt_tests += ddiff.032.clit dt_tests += ddiff.033.clit dt_tests += ddiff.034.clit dt_tests += ddiff.035.clit dt_tests += ddiff.036.clit dt_tests += ddiff.037.clit dt_tests += ddiff.038.clit dt_tests += ddiff.039.clit dt_tests += ddiff.040.clit dt_tests += ddiff.041.clit dt_tests += ddiff.042.clit dt_tests += ddiff.043.clit dt_tests += ddiff.044.clit dt_tests += ddiff.045.clit dt_tests += ddiff.046.clit dt_tests += ddiff.047.clit dt_tests += ddiff.048.clit dt_tests += ddiff.049.clit dt_tests += ddiff.050.clit dt_tests += ddiff.051.clit dt_tests += ddiff.052.clit dt_tests += ddiff.053.clit dt_tests += ddiff.054.clit dt_tests += ddiff.055.clit dt_tests += ddiff.056.clit dt_tests += ddiff.057.clit dt_tests += ddiff.058.clit dt_tests += ddiff.059.clit dt_tests += ddiff.060.clit dt_tests += ddiff.061.clit dt_tests += ddiff.062.clit dt_tests += ddiff.063.clit dt_tests += ddiff.064.clit dt_tests += ddiff.065.clit dt_tests += ddiff.066.clit dt_tests += ddiff.067.clit dt_tests += ddiff.068.clit dt_tests += ddiff.069.clit dt_tests += ddiff.070.clit dt_tests += ddiff.071.clit dt_tests += ddiff.072.clit EXTRA_DIST += some-dates-and-other-stuff.csv dt_tests += dgrep.001.clit dt_tests += dgrep.002.clit dt_tests += dgrep.003.clit dt_tests += dgrep.004.clit dt_tests += dgrep.005.clit dt_tests += dgrep.006.clit dt_tests += dgrep.007.clit dt_tests += dgrep.008.clit dt_tests += dgrep.009.clit dt_tests += dgrep.010.clit dt_tests += dgrep.011.clit dt_tests += dgrep.012.clit dt_tests += dgrep.013.clit dt_tests += dgrep.014.clit dt_tests += dgrep.015.clit dt_tests += dgrep.016.clit dt_tests += dgrep.017.clit dt_tests += dgrep.018.clit dt_tests += dgrep.019.clit dt_tests += dgrep.020.clit dt_tests += dgrep.021.clit dt_tests += dgrep.022.clit dt_tests += dgrep.023.clit dt_tests += dgrep.024.clit dt_tests += dgrep.025.clit dt_tests += dgrep.026.clit dt_tests += dgrep.027.clit dt_tests += dgrep.028.clit dt_tests += dgrep.029.clit dt_tests += dgrep.030.clit dt_tests += dgrep.031.clit dt_tests += dgrep.032.clit dt_tests += dgrep.033.clit dt_tests += dgrep.034.clit dt_tests += dgrep.035.clit dt_tests += dgrep.036.clit dt_tests += dgrep.037.clit dt_tests += dgrep.038.clit dt_tests += dgrep.039.clit dt_tests += dgrep.040.clit dt_tests += dgrep.041.clit dt_tests += dgrep.042.clit dt_tests += dgrep.043.clit dt_tests += dround.001.clit dt_tests += dround.002.clit dt_tests += dround.003.clit dt_tests += dround.004.clit dt_tests += dround.005.clit dt_tests += dround.006.clit dt_tests += dround.007.clit dt_tests += dround.008.clit dt_tests += dround.009.clit dt_tests += dround.010.clit dt_tests += dround.011.clit dt_tests += dround.012.clit dt_tests += dround.013.clit dt_tests += dround.014.clit dt_tests += dround.015.clit dt_tests += dround.016.clit dt_tests += dround.017.clit dt_tests += dround.018.clit dt_tests += dround.019.clit dt_tests += dround.020.clit dt_tests += dround.021.clit dt_tests += dround.022.clit dt_tests += dround.023.clit dt_tests += dround.024.clit dt_tests += dround.025.clit dt_tests += dround.026.clit dt_tests += dround.027.clit dt_tests += dround.028.clit dt_tests += dround.029.clit dt_tests += dround.030.clit dt_tests += dround.031.clit dt_tests += dround.032.clit dt_tests += dround.033.clit dt_tests += dround.034.clit dt_tests += dround.035.clit dt_tests += dround.036.clit dt_tests += tseq.01.clit dt_tests += tseq.02.clit dt_tests += tseq.03.clit dt_tests += tseq.04.clit dt_tests += tseq.05.clit dt_tests += tseq.06.clit dt_tests += tseq.07.clit dt_tests += tseq.08.clit dt_tests += tseq.09.clit dt_tests += tseq.10.clit dt_tests += tseq.11.clit dt_tests += tseq.12.clit dt_tests += tseq.13.clit dt_tests += tseq.14.clit dt_tests += tseq.15.clit dt_tests += tseq.16.clit dt_tests += tseq.17.clit dt_tests += tseq.18.clit dt_tests += tseq.19.clit dt_tests += tdiff.001.clit dt_tests += tdiff.002.clit dt_tests += tdiff.003.clit dt_tests += tdiff.004.clit dt_tests += tdiff.005.clit dt_tests += tdiff.006.clit dt_tests += tdiff.007.clit dt_tests += tdiff.008.clit dt_tests += tdiff.009.clit dt_tests += tdiff.010.clit dt_tests += tdiff.011.clit dt_tests += tdiff.012.clit dt_tests += tdiff.013.clit dt_tests += tadd.001.clit dt_tests += tadd.002.clit dt_tests += tadd.003.clit dt_tests += tadd.004.clit dt_tests += tadd.005.clit dt_tests += tadd.006.clit dt_tests += tadd.007.clit dt_tests += tadd.008.clit dt_tests += tadd.009.clit dt_tests += tadd.010.clit dt_tests += tadd.011.clit dt_tests += tgrep.001.clit dt_tests += tgrep.002.clit dt_tests += tgrep.003.clit dt_tests += ttest.001.clit dt_tests += ttest.002.clit dt_tests += ttest.003.clit dt_tests += ttest.004.clit dt_tests += ttest.005.clit dt_tests += ttest.006.clit dt_tests += ttest.007.clit dt_tests += tconv.001.clit dt_tests += tconv.002.clit dt_tests += tconv.003.clit dt_tests += tconv.004.clit dt_tests += tconv.005.clit dt_tests += tconv.006.clit dt_tests += tconv.007.clit dt_tests += tconv.008.clit dt_tests += tconv.009.clit dt_tests += tconv.010.clit dt_tests += tconv.011.clit dt_tests += tconv.012.clit dt_tests += tconv.013.clit dt_tests += tconv.014.clit dt_tests += tround.001.clit dt_tests += tround.002.clit dt_tests += tround.003.clit dt_tests += tround.004.clit dt_tests += tround.005.clit dt_tests += tround.006.clit dt_tests += dtconv.001.clit dt_tests += dtconv.002.clit dt_tests += dtconv.003.clit dt_tests += dtconv.004.clit dt_tests += dtconv.005.clit dt_tests += dtconv.006.clit dt_tests += dtconv.007.clit dt_tests += dtconv.008.clit dt_tests += dtconv.009.clit dt_tests += dtconv.010.clit dt_tests += dtconv.011.clit dt_tests += dtconv.012.clit dt_tests += dtconv.013.clit dt_tests += dtconv.014.clit dt_tests += dtconv.015.clit dt_tests += dtconv.016.clit dt_tests += dtconv.017.clit dt_tests += dtconv.018.clit dt_tests += dtconv.019.clit dt_tests += dtconv.020.clit dt_tests += dtconv.021.clit dt_tests += dtconv.022.clit dt_tests += dtconv.023.clit if ZONEINFO_UTC_RIGHT dt_tests += dtconv.024.clit dt_tests += dtconv.025.clit dt_tests += dtconv.026.clit dt_tests += dtconv.027.clit dt_tests += dtconv.028.clit dt_tests += dtconv.029.clit dt_tests += dtconv.030.clit dt_tests += dtconv.031.clit dt_tests += dtconv.032.clit dt_tests += dtconv.033.clit endif ZONEINFO_UTC_RIGHT dt_tests += dtconv.034.clit dt_tests += dtconv.035.clit dt_tests += dtconv.036.clit dt_tests += dtconv.037.clit dt_tests += dtconv.038.clit dt_tests += dtconv.039.clit dt_tests += dtconv.040.clit dt_tests += dtconv.041.clit dt_tests += dtconv.042.clit dt_tests += dtconv.043.clit dt_tests += dtconv.044.clit dt_tests += dtconv.045.clit dt_tests += dtconv.046.clit dt_tests += dtconv.047.clit dt_tests += dtconv.048.clit dt_tests += dtconv.049.clit dt_tests += dtconv.050.clit dt_tests += dtconv.051.clit dt_tests += dtconv.052.clit dt_tests += dtconv.053.clit dt_tests += dtconv.054.clit dt_tests += dtconv.055.clit dt_tests += dtconv.056.clit dt_tests += dtconv.057.clit dt_tests += dtconv.058.clit dt_tests += dtconv.059.clit dt_tests += dtconv.060.clit dt_tests += dtconv.061.clit dt_tests += dtconv.062.clit dt_tests += dtconv.063.clit dt_tests += dtconv.064.clit dt_tests += dtconv.065.clit dt_tests += dtconv.066.clit dt_tests += dtconv.067.clit dt_tests += dtconv.068.clit dt_tests += dtconv.069.clit dt_tests += dtconv.070.clit dt_tests += dtconv.071.clit dt_tests += dtconv.072.clit dt_tests += convt.ymcw-ymd.clit dt_tests += convt.ymcw-ywd.clit dt_tests += convt.ymcw-yd.clit dt_tests += convt.ymd-ymcw.clit dt_tests += convt.ymd-ywd.clit dt_tests += convt.ymd-yd.clit dt_tests += convt.ywd-ymcw.clit dt_tests += convt.ywd-ymd.clit dt_tests += convt.ywd-yd.clit dt_tests += convt.yd-ymcw.clit dt_tests += convt.yd-ymd.clit dt_tests += convt.yd-ywd.clit dt_tests += add.ymcw-1d.clit dt_tests += add.ymd-1d.clit dt_tests += add.ywd-1d.clit dt_tests += add.yd-1d.clit dt_tests += add.ymcw-1w.clit dt_tests += add.ymd-1w.clit dt_tests += add.ywd-1w.clit dt_tests += add.yd-1w.clit dt_tests += add.ymcw-1y.clit dt_tests += add.ymd-1y.clit dt_tests += add.ywd-1y.clit dt_tests += add.yd-1y.clit dt_tests += dtseq.01.clit dt_tests += dtseq.02.clit dt_tests += dtseq.03.clit dt_tests += dtseq.04.clit dt_tests += dtseq.05.clit dt_tests += dtseq.06.clit dt_tests += dtseq.07.clit dt_tests += dtseq.08.clit dt_tests += dtseq.09.clit dt_tests += dtseq.10.clit dt_tests += dtseq.11.clit dt_tests += dtseq.12.clit dt_tests += dtadd.001.clit dt_tests += dtadd.002.clit dt_tests += dtadd.003.clit dt_tests += dtadd.004.clit dt_tests += dtadd.005.clit dt_tests += dtadd.006.clit dt_tests += dtadd.007.clit dt_tests += dtadd.008.clit dt_tests += dtadd.009.clit dt_tests += dtadd.010.clit dt_tests += dtadd.011.clit dt_tests += dtadd.012.clit dt_tests += dtadd.013.clit dt_tests += dtadd.014.clit dt_tests += dtadd.015.clit dt_tests += dtadd.016.clit dt_tests += dtadd.017.clit dt_tests += dtadd.018.clit dt_tests += dtadd.019.clit dt_tests += dtadd.020.clit dt_tests += dtadd.021.clit dt_tests += dtadd.022.clit dt_tests += dtadd.023.clit dt_tests += dtadd.024.clit dt_tests += dtadd.025.clit dt_tests += dtadd.026.clit dt_tests += dtadd.027.clit dt_tests += dtadd.028.clit dt_tests += dtadd.029.clit if WITH_LEAP_SECONDS dt_tests += dtadd.030.clit dt_tests += dtadd.031.clit endif ## WITH_LEAP_SECONDS dt_tests += dtadd.032.clit dt_tests += dtadd.033.clit if WITH_LEAP_SECONDS dt_tests += dtadd.034.clit dt_tests += dtadd.035.clit endif ## WITH_LEAP_SECONDS dt_tests += dtadd.036.clit dt_tests += dtadd.037.clit dt_tests += dtadd.038.clit dt_tests += dtadd.039.clit dt_tests += dtadd.040.clit ## multi-sed dt_tests += dtadd.041.clit dt_tests += dtadd.042.clit dt_tests += dtadd.043.clit dt_tests += dtadd.044.clit dt_tests += dtadd.045.clit dt_tests += dtadd.046.clit dt_tests += dtadd.047.clit dt_tests += dtadd.048.clit dt_tests += dtadd.049.clit dt_tests += dtadd.050.clit dt_tests += dtadd.051.clit dt_tests += dtadd.052.clit dt_tests += dtadd.053.clit dt_tests += dtadd.054.clit dt_tests += dtadd.055.clit dt_tests += dtgrep.001.clit dt_tests += dtgrep.002.clit dt_tests += dtgrep.003.clit dt_tests += dtgrep.004.clit dt_tests += dtgrep.005.clit dt_tests += dtgrep.006.clit dt_tests += dtgrep.007.clit dt_tests += dtgrep.008.clit dt_tests += dtgrep.009.clit dt_tests += dtgrep.010.clit dt_tests += dtgrep.011.clit dt_tests += dtgrep.012.clit dt_tests += dtgrep.013.clit dt_tests += dtgrep.014.clit dt_tests += dttest.001.clit dt_tests += dttest.002.clit dt_tests += dttest.003.clit dt_tests += dttest.004.clit dt_tests += dttest.005.clit dt_tests += dttest.006.clit dt_tests += dttest.007.clit dt_tests += dttest.008.clit dt_tests += dttest.009.clit dt_tests += dttest.010.clit dt_tests += dtdiff.001.clit dt_tests += dtdiff.002.clit dt_tests += dtdiff.003.clit dt_tests += dtdiff.004.clit dt_tests += dtdiff.005.clit dt_tests += dtdiff.006.clit dt_tests += dtdiff.007.clit dt_tests += dtdiff.008.clit dt_tests += dtdiff.009.clit dt_tests += dtdiff.010.clit dt_tests += dtdiff.011.clit dt_tests += dtdiff.012.clit dt_tests += dtdiff.013.clit dt_tests += dtdiff.014.clit dt_tests += dtdiff.015.clit dt_tests += dtdiff.016.clit dt_tests += dtdiff.017.clit dt_tests += dtdiff.018.clit if WITH_LEAP_SECONDS dt_tests += dtdiff.019.clit dt_tests += dtdiff.020.clit dt_tests += dtdiff.021.clit dt_tests += dtdiff.022.clit endif ## WITH_LEAP_SECONDS dt_tests += dtdiff.023.clit dt_tests += dtdiff.024.clit dt_tests += dtdiff.025.clit dt_tests += dtdiff.026.clit dt_tests += dtdiff.027.clit dt_tests += dtdiff.028.clit dt_tests += dtdiff.029.clit dt_tests += dtdiff.030.clit dt_tests += dtdiff.031.clit dt_tests += dtdiff.032.clit dt_tests += dtdiff.033.clit dt_tests += dtdiff.034.clit dt_tests += dtdiff.035.clit dt_tests += dtdiff.036.clit dt_tests += dtdiff.037.clit dt_tests += dtdiff.038.clit dt_tests += dtdiff.039.clit dt_tests += dtdiff.040.clit dt_tests += dtdiff.041.clit dt_tests += dtdiff.042.clit dt_tests += dtdiff.043.clit dt_tests += dtdiff.044.clit dt_tests += dtdiff.045.clit dt_tests += dtdiff.046.clit dt_tests += dtdiff.047.clit dt_tests += dtround.001.clit dt_tests += dtround.002.clit dt_tests += dtround.003.clit dt_tests += dtround.004.clit dt_tests += dtround.005.clit dt_tests += dtround.006.clit dt_tests += dtround.007.clit dt_tests += dtround.008.clit dt_tests += dtround.009.clit dt_tests += dtround.010.clit dt_tests += dtround.011.clit dt_tests += dtround.012.clit dt_tests += dtround.013.clit dt_tests += dtround.014.clit dt_tests += dtround.015.clit dt_tests += dtround.016.clit dt_tests += dzone.001.clit dt_tests += dzone.002.clit dt_tests += dzone.003.clit dt_tests += dzone.004.clit dt_tests += dzone.005.clit dt_tests += dzone.006.clit dt_tests += dzone.007.clit dt_tests += dzone.008.clit dt_tests += dzone.009.clit dt_tests += dzone.010.clit dt_tests += dzone.011.clit dt_tests += dzone.012.clit dt_tests += dzone.013.clit dt_tests += dzone.014.clit dt_tests += dsort.001.clit dt_tests += dsort.002.clit dt_tests += dsort.003.clit dt_tests += dsort.004.clit dt_tests += dsort.005.clit dt_tests += dsort.006.clit dt_tests += dsort.007.clit EXTRA_DIST += caev_01.txt EXTRA_DIST += caev_02.txt dt_tests += strptime.001.clit dt_tests += strptime.002.clit dt_tests += strptime.003.clit ## testing the prchunker dt_tests += prchunk.001.clit dt_tests += prchunk.002.clit dt_tests += prchunk.003.clit dt_tests += prchunk.004.clit dt_tests += prchunk.005.clit dt_tests += prchunk.006.clit ## testing tzmaps, regardless if the official ones are here or not EXTRA_DIST += dummy.tzmap built_nodist_sources += dummy.tzmcc TESTS_ENVIRONMENT += TZMAP_DIR=$(builddir) TESTS_ENVIRONMENT += LOCALE_FILE=$(top_srcdir)/data/locale dt_tests += tzmap.001.clit dt_tests += tzmap.002.clit dt_tests += tzmap.003.clit dt_tests += tzmap.004.clit ## make sure our the maps we ship are clean dt_tests += tzmap_check_01.clit dt_tests += tzmap_check_02.clit TESTS_ENVIRONMENT += TZMAP=$(top_builddir)/lib/tzmap ## military midnight dt_tests += mil-midnight.001.clit dt_tests += mil-midnight.002.clit dt_tests += mil-midnight.003.clit dt_tests += mil-midnight.004.clit dt_tests += mil-midnight.005.clit dt_tests += mil-midnight.006.clit dt_tests += mil-midnight.007.clit dt_tests += mil-midnight.008.clit dt_tests += mil-midnight.009.clit dt_tests += mil-midnight.010.clit ## we should check if the zones in these tests actually exist ## also failing tests here should be soft-fails because that could ## easily be an outdated zoneinfo file dt_tests += dtz.001.clit dt_tests += dtz.002.clit check_PROGRAMS += struct-1 check_PROGRAMS += struct-2 check_PROGRAMS += struct-3 check_PROGRAMS += struct-4 check_PROGRAMS += struct-5 check_PROGRAMS += struct-6 check_PROGRAMS += struct-7 check_PROGRAMS += struct-8 check_PROGRAMS += struct-9 check_PROGRAMS += enum-1 check_PROGRAMS += dtcore-strp check_PROGRAMS += dtcore-conv check_PROGRAMS += dtcore-add check_PROGRAMS += time-core-add check_PROGRAMS += basic_ymd_get_wday check_PROGRAMS += basic_get_jan01_wday check_PROGRAMS += basic_md_get_yday check_PROGRAMS += basic_get_dom_wday check_PROGRAMS += strtoi-bench check_PROGRAMS += strtoi-1 check_PROGRAMS += itostr-1 check_PROGRAMS += itostr-2 check_PROGRAMS += itostr-3 check_PROGRAMS += itostr-4 bin_tests += struct-1 bin_tests += struct-2 bin_tests += struct-3 bin_tests += struct-4 bin_tests += struct-5 bin_tests += struct-6 bin_tests += struct-7 bin_tests += struct-8 bin_tests += struct-9 bin_tests += enum-1 bin_tests += dtcore-strp bin_tests += dtcore-conv bin_tests += dtcore-add bin_tests += time-core-add bin_tests += basic_ymd_get_wday bin_tests += basic_get_jan01_wday bin_tests += basic_get_dom_wday bin_tests += basic_md_get_yday dtcore_strp_LDADD = $(DT_LIBS) dtcore_conv_LDADD = $(DT_LIBS) dtcore_add_LDADD = $(DT_LIBS) time_core_add_LDADD = $(DT_LIBS) dt_tests += strtoi.001.clit dt_tests += itostr.001.clit dt_tests += itostr.002.clit dt_tests += itostr.003.clit dt_tests += itostr.004.clit ## batch checks batch_tests += dseq-cnt.1.sh if HAVE_GDATE TESTS_ENVIRONMENT += have_gdate_2039="$(have_gdate_2039)" batch_tests += dseq-cnt.2.sh batch_tests += dseq-cnt.3.sh batch_tests += dconv-batch.1.sh batch_tests += dconv-batch.2.sh endif HAVE_GDATE ## tzmcc rule SUFFIXES += .tzmap SUFFIXES += .tzmcc .tzmap.tzmcc: -$(AM_V_GEN) $(top_builddir)/lib/tzmap cc -o $@ $< clean-local: -rm -rf *.tmpd ## Makefile.am ends here dateutils-0.4.5/test/add.yd-1d.clit000066400000000000000000000003201335042257000170130ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq "1917-01-01" "2399-12-31" -f "yd" > "add.yd-1d.ref" $ dadd +1d < "add.yd-1d.ref" | dadd -1d < "add.yd-1d.ref" $ rm -- "add.yd-1d.ref" $ ## add.yd-1d.clit dateutils-0.4.5/test/add.yd-1w.clit000066400000000000000000000003201335042257000170360ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq "1917-01-01" "2399-12-31" -f "yd" > "add.yd-1w.ref" $ dadd +1w < "add.yd-1w.ref" | dadd -1w < "add.yd-1w.ref" $ rm -- "add.yd-1w.ref" $ ## add.yd-1w.clit dateutils-0.4.5/test/add.yd-1y.clit000066400000000000000000000003271335042257000170470ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq "1917-01-01" "2071-12-31" -f "yd" > "add.yd-28y.ref" $ dadd +28y < "add.yd-28y.ref" | dadd -28y < "add.yd-28y.ref" $ rm -- "add.yd-28y.ref" $ ## add.yd-28y.clit dateutils-0.4.5/test/add.ymcw-1d.clit000066400000000000000000000003341335042257000173630ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq "1917-01-01" "2399-12-31" -f "ymcw" > "add.ymcw-1d.ref" $ dadd +1d < "add.ymcw-1d.ref" | dadd -1d < "add.ymcw-1d.ref" $ rm -- "add.ymcw-1d.ref" $ ## add.ymcw-1d.clit dateutils-0.4.5/test/add.ymcw-1w.clit000066400000000000000000000003341335042257000174060ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq "1917-01-01" "2399-12-31" -f "ymcw" > "add.ymcw-1w.ref" $ dadd +1w < "add.ymcw-1w.ref" | dadd -1w < "add.ymcw-1w.ref" $ rm -- "add.ymcw-1w.ref" $ ## add.ymcw-1w.clit dateutils-0.4.5/test/add.ymcw-1y.clit000066400000000000000000000003431335042257000174100ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq "1917-01-01" "2071-12-31" -f "ymcw" > "add.ymcw-28y.ref" $ dadd +28y < "add.ymcw-28y.ref" | dadd -28y < "add.ymcw-28y.ref" $ rm -- "add.ymcw-28y.ref" $ ## add.ymcw-28y.clit dateutils-0.4.5/test/add.ymd-1d.clit000066400000000000000000000003261335042257000171760ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq "1917-01-01" "2399-12-31" -f "ymd" > "add.ymd-1d.ref" $ dadd +1d < "add.ymd-1d.ref" | dadd -1d < "add.ymd-1d.ref" $ rm -- "add.ymd-1d.ref" $ ## add.ymd-1d.clit dateutils-0.4.5/test/add.ymd-1w.clit000066400000000000000000000003261335042257000172210ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq "1917-01-01" "2399-12-31" -f "ymd" > "add.ymd-1w.ref" $ dadd +1w < "add.ymd-1w.ref" | dadd -1w < "add.ymd-1w.ref" $ rm -- "add.ymd-1w.ref" $ ## add.ymd-1w.clit dateutils-0.4.5/test/add.ymd-1y.clit000066400000000000000000000003351335042257000172230ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq "1917-01-01" "2071-12-31" -f "ymd" > "add.ymd-28y.ref" $ dadd +28y < "add.ymd-28y.ref" | dadd -28y < "add.ymd-28y.ref" $ rm -- "add.ymd-28y.ref" $ ## add.ymd-28y.clit dateutils-0.4.5/test/add.ywd-1d.clit000066400000000000000000000003261335042257000172100ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq "1917-01-01" "2399-12-31" -f "ywd" > "add.ywd-1d.ref" $ dadd +1d < "add.ywd-1d.ref" | dadd -1d < "add.ywd-1d.ref" $ rm -- "add.ywd-1d.ref" $ ## add.ywd-1d.clit dateutils-0.4.5/test/add.ywd-1w.clit000066400000000000000000000003261335042257000172330ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq "1917-01-01" "2399-12-31" -f "ywd" > "add.ywd-1w.ref" $ dadd +1w < "add.ywd-1w.ref" | dadd -1w < "add.ywd-1w.ref" $ rm -- "add.ywd-1w.ref" $ ## add.ywd-1w.clit dateutils-0.4.5/test/add.ywd-1y.clit000066400000000000000000000003351335042257000172350ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq "1917-01-01" "2071-12-31" -f "ywd" > "add.ywd-28y.ref" $ dadd +28y < "add.ywd-28y.ref" | dadd -28y < "add.ywd-28y.ref" $ rm -- "add.ywd-28y.ref" $ ## add.ywd-28y.clit dateutils-0.4.5/test/basic_get_dom_wday.c000066400000000000000000000013741335042257000204520ustar00rootroot00000000000000#if defined HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include "strops.h" #include "strops.c" #include "token.h" #include "token.c" #include "date-core.h" #include "date-core.c" #include "dt-locale.h" #include "dt-locale.c" static unsigned int super(void) { unsigned int res = 0; for (int y = 1917; y < 2199; y++) { for (int m = 1; m <= 12; m ++) { for (int d = 1; d <= 28; d++) { dt_dow_t w = __get_dom_wday(y, m, d); res += y * m * (w == DT_SUNDAY ? 0 : w) + d; } } } return res; } int main(void) { unsigned int supersum = 0; for (size_t i = 0; i < 512; i++) { supersum += super(); } printf("super %u\n", supersum); if (supersum != 1486417920U) { return 1; } return 0; } /* basic_get_wday.c ends here */ dateutils-0.4.5/test/basic_get_jan01_wday.c000066400000000000000000000012541335042257000206010ustar00rootroot00000000000000#if defined HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include "strops.h" #include "strops.c" #include "token.h" #include "token.c" #include "date-core.h" #include "date-core.c" #include "dt-locale.h" #include "dt-locale.c" static unsigned int super(unsigned int res) { for (int y = 1917; y < 2199; y++) { dt_dow_t w; w = __get_jan01_wday(y); res += y * (w == DT_SUNDAY ? 0 : w); } return res; } int main(void) { unsigned int supersum = 0; for (size_t i = 0; i < 1024 * 1024; i++) { supersum += super(supersum); } printf("super %u\n", supersum); if (supersum != 4293232620U) { return 1; } return 0; } /* basic_get_jan01_wday.c ends here */ dateutils-0.4.5/test/basic_md_get_yday.c000066400000000000000000000020521335042257000202670ustar00rootroot00000000000000#if defined HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include "strops.h" #include "strops.c" #include "token.h" #include "token.c" #include "date-core.h" #include "date-core.c" #include "dt-locale.h" #include "dt-locale.c" static unsigned int super(unsigned int res) { for (int y = 1917; y < 2299; y++) { for (int m = 1; m <= 12; m++) { for (int d = 0; d < 32; d++) { unsigned int yd; yd = __md_get_yday(y, m, d); res += y * m * yd + d; } } } return res; } #if 0 static unsigned int hyper(unsigned int hyper) { dt_ymd_t x; for (int y = 1917; y < 4096; y++) { for (int m = 1; m <= 12; m++) { for (int d = 0; d < 32; d++) { unsigned int yd; x.y = y; x.m = m; x.d = d; yd = __ymd_get_yday(x); hyper += yd; } } } return hyper; } #endif int main(void) { unsigned int supersum = 0; for (size_t i = 0; i < 4096; i++) { supersum += super(supersum); } printf("super %u\n", supersum); if (supersum != 2780223808U) { return 1; } return 0; } /* basic_md_get_yday.c ends here */ dateutils-0.4.5/test/basic_ymd_get_wday.c000066400000000000000000000014731335042257000204640ustar00rootroot00000000000000#if defined HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include "strops.h" #include "strops.c" #include "token.h" #include "token.c" #include "date-core.h" #include "date-core.c" #include "dt-locale.h" #include "dt-locale.c" static unsigned int super(void) { dt_ymd_t x = {0}; unsigned int res = 0; for (int y = 1917; y < 2199; y++) { for (int m = 1; m <= 12; m ++) { for (int d = 1; d <= 28; d++) { dt_dow_t w; x.y = y; x.m = m; x.d = d; w = __ymd_get_wday(x); res += y * m * (w == DT_SUNDAY ? 0 : w) + d; } } } return res; } int main(void) { unsigned int supersum = 0; for (size_t i = 0; i < 512; i++) { supersum += super(); } printf("super %u\n", supersum); if (supersum != 1486417920U) { return 1; } return 0; } /* basic_ymd_get_wday.c ends here */ dateutils-0.4.5/test/caev_01.txt000066400000000000000000000007371335042257000164640ustar00rootroot000000000000002009-06-03 caev="DVCA" secu="VOD" exch="XLON" xdte="2009-06-03" nett/GBX="5.2" 2011-11-16 caev="DVCA" secu="VOD" exch="XLON" xdte="2011-11-16" nett/GBX="3.05" 2013-11-20 caev="DVCA" secu="VOD" exch="XLON" xdte="2013-11-20" nett/GBX="3.53" 2012-06-06 caev="DVCA" secu="VOD" exch="XLON" xdte="2012-06-06" nett/GBX="6.47" 2013-06-12 caev="DVCA" secu="VOD" exch="XLON" xdte="2013-06-12" nett/GBX="6.92" 2010-11-17 caev="DVCA" secu="VOD" exch="XLON" xdte="2010-11-17" nett/GBX="2.85" dateutils-0.4.5/test/caev_02.txt000066400000000000000000000010371335042257000164570ustar00rootroot000000000000002009-06-03 caev="DVCA" secu="VOD" exch="XLON" xdte="2009-06-03" nett/GBX="5.2" 2011-11-16 caev="DVCA" secu="VOD" exch="XLON" xdte="2011-11-16" nett/GBX="3.05" 2013-11-20 caev="DVCA" secu="VOD" exch="XLON" xdte="2013-11-20" nett/GBX="3.53" 2010-11-17 caev="XXXX" secu="VOD" exch="XLON" xdte="2010-11-17" 2012-06-06 caev="DVCA" secu="VOD" exch="XLON" xdte="2012-06-06" nett/GBX="6.47" 2013-06-12 caev="DVCA" secu="VOD" exch="XLON" xdte="2013-06-12" nett/GBX="6.92" 2010-11-17 caev="DVCA" secu="VOD" exch="XLON" xdte="2010-11-17" nett/GBX="2.85" dateutils-0.4.5/test/clitosis.am000066400000000000000000000012251335042257000166460ustar00rootroot00000000000000## assumes TEST_EXTENSIONS, BUILT_SOURCES, check_PROGRAMS have been set TEST_EXTENSIONS += .clit CLIT_LOG_COMPILER = $(builddir)/clitosis ## our friendly helper check_PROGRAMS += clitosis clitosis_SOURCES = clitosis.c clitosis.yuck clitosis_CPPFLAGS = -D_POSIX_C_SOURCE=200112L -D_XOPEN_SOURCE=600 -D_BSD_SOURCE clitosis_CPPFLAGS += -D_ALL_SOURCE -D_NETBSD_SOURCE clitosis_CPPFLAGS += -UHAVE_VERSION_H clitosis_LDADD = if HAVE_PTY_H clitosis_LDADD += -lutil endif HAVE_PTY_H built_dist_sources += clitosis.yucc ## yuck rule SUFFIXES += .yuck SUFFIXES += .yucc .yuck.yucc: $(AM_V_GEN) PATH=$(top_builddir)/build-aux:"$${PATH}" \ yuck$(EXEEXT) gen -o $@ $< dateutils-0.4.5/test/clitosis.c000066400000000000000000001135751335042257000165070ustar00rootroot00000000000000/*** clitosis.c -- command-line-interface tester on shell input syntax * * Copyright (C) 2013-2018 Sebastian Freundt * * Author: Sebastian Freundt * * This file is part of clitosis. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***/ #if defined HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined HAVE_PTY_H # include #endif /* HAVE_PTY_H */ /* check for me */ #include #if !defined LIKELY # define LIKELY(_x) __builtin_expect((_x), 1) #endif /* !LIKELY */ #if !defined UNLIKELY # define UNLIKELY(_x) __builtin_expect((_x), 0) #endif /* UNLIKELY */ #if !defined countof # define countof(x) (sizeof(x) / sizeof(*x)) #endif /* !countof */ #if !defined strlenof # define strlenof(x) (sizeof(x) - 1U) #endif /* !strlenof */ #if !defined with # define with(args...) for (args, *__ep__ = (void*)1; __ep__; __ep__ = 0) #endif /* !with */ #if !defined PATH_MAX # define PATH_MAX 256U #endif /* !PATH_MAX */ #if defined HAVE_SPLICE && !defined SPLICE_F_MOVE && !defined _AIX /* just so we don't have to use _GNU_SOURCE declare prototype of splice() */ # if defined __INTEL_COMPILER # pragma warning(disable:1419) # endif /* __INTEL_COMPILER */ extern ssize_t splice(int, loff_t*, int, loff_t*, size_t, unsigned int); # define SPLICE_F_MOVE (0U) # if defined __INTEL_COMPILER # pragma warning(default:1419) # endif /* __INTEL_COMPILER */ #elif !defined SPLICE_F_MOVE # define SPLICE_F_MOVE (0) #endif /* !SPLICE_F_MOVE */ typedef struct clitf_s clitf_t; typedef struct clit_buf_s clit_buf_t; typedef struct clit_bit_s clit_bit_t; typedef struct clit_tst_s *clit_tst_t; struct clitf_s { size_t z; void *d; }; struct clit_buf_s { size_t z; const char *d; }; /** * A clit bit can be an ordinary memory buffer (z > 0 && d), * a file descriptor (fd != 0 && d == NULL), or a file name (z == -1UL && fn) */ struct clit_bit_s { size_t z; const char *d; }; struct clit_opt_s { unsigned int timeo; unsigned int verbosep:1; unsigned int ptyp:1; unsigned int keep_going_p:1; unsigned int shcmdp:1; /* just some padding to start afresh on an 8-bit boundary */ unsigned int:4; unsigned int xcod:8; /* use this instead of /bin/sh */ char *shcmd; }; struct clit_chld_s { int pin; int pou; int per; pid_t chld; pid_t diff; pid_t feed; /* options to control behaviour */ struct clit_opt_s options; /* cmd'ified version of options.shell */ char **huskv; }; /* a test is the command (including stdin), stdout result, and stderr result */ struct clit_tst_s { clit_bit_t cmd; clit_bit_t out; clit_bit_t err; clit_bit_t rest; /* specific per-test flags */ /** don't fail when the actual output differs from th expected output */ unsigned int ign_out:1; /** don't fail when the command returns non-SUCCESS */ unsigned int ign_ret:1; /** don't pass the output on to external differ */ unsigned int supp_diff:1; /** expand the proto-output as though it was a shell here-document */ unsigned int xpnd_proto:1; /* padding */ unsigned int:5; /** expect this return code, or any but 0 if all bits are set */ unsigned int exp_ret:8; }; typedef enum { CLIT_END_UNKNOWN, CLIT_END_BIG, CLIT_END_LITTLE, CLIT_END_MIDDLE, } clit_end_t; static sigset_t fatal_signal_set[1]; static sigset_t empty_signal_set[1]; static const char dflt_diff[] = "diff"; static const char *cmd_diff = dflt_diff; static void __attribute__((format(printf, 1, 2))) error(const char *fmt, ...) { va_list vap; va_start(vap, fmt); vfprintf(stderr, fmt, vap); va_end(vap); if (errno) { fputs(": ", stderr); fputs(strerror(errno), stderr); } fputc('\n', stderr); return; } static inline __attribute__((const, pure, always_inline)) char* deconst(const char *s) { union { const char *c; char *p; } x = {s}; return x.p; } static clit_end_t get_endianness(void) { static const unsigned int u = 0x01234567U; unsigned char p[sizeof(u)]; memcpy(p, &u, sizeof(u)); switch (*p) { case 0x01U: return CLIT_END_BIG; case 0x67U: return CLIT_END_LITTLE; case 0x23U: if (p[1U] == 0x01U && p[2U] == 0x67U && p[3U] == 0x45U) { return CLIT_END_MIDDLE; } /*@fallthrough@*/ default: break; } return CLIT_END_UNKNOWN; } /* imported code */ /*** fast_strstr.c * * This algorithm is licensed under the open-source BSD3 license * * Copyright (c) 2014, Raphael Javaux * All rights reserved. * * Licence text, see above. * * The code has been modified to mimic memmem(). * **/ /** * Finds the first occurrence of the sub-string needle in the string haystack. * Returns NULL if needle was not found. */ static char* xmemmem(const char *hay, const size_t hayz, const char *ndl, const size_t ndlz) { const char *const eoh = hay + hayz; const char *const eon = ndl + ndlz; const char *hp; const char *np; const char *cand; unsigned int hsum; unsigned int nsum; unsigned int eqp; /* trivial checks first * a 0-sized needle is defined to be found anywhere in haystack * then run strchr() to find a candidate in HAYSTACK (i.e. a portion * that happens to begin with *NEEDLE) */ if (ndlz == 0UL) { return deconst(hay); } else if ((hay = memchr(hay, *ndl, hayz)) == NULL) { /* trivial */ return NULL; } /* First characters of haystack and needle are the same now. Both are * guaranteed to be at least one character long. Now computes the sum * of characters values of needle together with the sum of the first * needle_len characters of haystack. */ for (hp = hay + 1U, np = ndl + 1U, hsum = *hay, nsum = *hay, eqp = 1U; hp < eoh && np < eon; hsum ^= *hp, nsum ^= *np, eqp &= *hp == *np, hp++, np++); /* HP now references the (NZ + 1)-th character. */ if (np < eon) { /* haystack is smaller than needle, :O */ return NULL; } else if (eqp) { /* found a match */ return deconst(hay); } /* now loop through the rest of haystack, * updating the sum iteratively */ for (cand = hay; hp < eoh; hp++) { hsum ^= *cand++; hsum ^= *hp; /* Since the sum of the characters is already known to be * equal at that point, it is enough to check just NZ - 1 * characters for equality, * also CAND is by design < HP, so no need for range checks */ if (hsum == nsum && memcmp(cand, ndl, ndlz - 1U) == 0) { return deconst(cand); } } return NULL; } static char* xstrndup(const char *s, size_t z) { char *res; if ((res = malloc(z + 1U))) { memcpy(res, s, z); res[z] = '\0'; } return res; } static char** cmdify(char *restrict cmd) { /* prep for about 16 params */ char **v = calloc(16U, sizeof(*v)); if (LIKELY(v != NULL)) { const char *ifs = getenv("IFS") ?: " \t\n"; size_t i = 0U; v[0U] = strtok(cmd, ifs); do { if (UNLIKELY((i % 16U) == 15U)) { void *nuv; nuv = realloc(v, (i + 1U + 16U) * sizeof(*v)); if (UNLIKELY(nuv == NULL)) { free(v); return NULL; } v = nuv; } } while ((v[++i] = strtok(NULL, ifs)) != NULL); } return v; } /* takes ideas from Gregory Pakosz's whereami */ static char* get_argv0dir(const char *argv0) { /* return current executable */ char *res; if (0) { #if 0 #elif defined __linux__ /* don't rely on argv0 at all */ } else if (1) { if ((res = realpath("/proc/self/exe", NULL)) == NULL) { /* we've got a plan B */ goto planb; } #elif defined __APPLE__ && defined __MACH__ } else if (1) { char buf[PATH_MAX]; uint32_t bsz = strlenof(buf); buf[bsz] = '\0'; if (_NSGetExecutablePath(buf, &bsz) < 0) { /* plan B again */ goto planb; } /* strdup BUF quickly */ res = strdup(buf); #elif defined __NetBSD__ } else if (1) { static const char myself[] = "/proc/curproc/exe"; char buf[PATH_MAX]; ssize_t z; if (UNLIKELY((z = readlink(myself, buf, bsz)) < 0)) { /* plan B */ goto planb; } /* strndup him */ res = xstrndup(buf, z); #elif defined __DragonFly__ } else if (1) { static const char myself[] = "/proc/curproc/file"; char buf[PATH_MAX]; ssize_t z; if (UNLIKELY((z = readlink(myself, buf, bsz)) < 0)) { /* blimey, proceed with plan B */ goto planb; } /* strndup him */ res = xstrndup(buf, z); #elif defined __FreeBSD__ } else if (1) { int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1}; char buf[PATH_MAX]; size_t z = strlenof(buf); /* make sure that \0 terminator fits */ buf[z] = '\0'; if (UNLIKELY(sysctl(mib, countof(mib), buf, &z, NULL, 0) < 0)) { /* no luck today */ goto planb; } /* make the result our own */ res = strdup(buf); #elif defined __sun || defined sun } else if (1) { char buf[PATH_MAX]; ssize_t z; snprintf(buf, sizeof(buf), "/proc/%d/path/a.out", getpid()); if (UNLIKELY((z = readlink(buf, buf, sizeof(buf))) < 0)) { /* nope, plan A failed */ goto planb; } res = xstrndup(buf, z); #endif /* OS */ } else { size_t argz0; planb: /* backup plan, massage argv0 */ if (argv0 == NULL) { return NULL; } /* otherwise copy ARGV0, or rather the first PATH_MAX chars */ for (argz0 = 0U; argz0 < PATH_MAX && argv0[argz0]; argz0++); res = xstrndup(argv0, argz0); } /* path extraction aka dirname'ing, absolute or otherwise */ if (res == NULL) { return NULL; } with (char *dir0 = strrchr(res, '/')) { if (dir0 == NULL) { free(res); return NULL; } *dir0 = '\0'; } return res; } static void free_argv0dir(char *a0) { free(a0); return; } /* clit bit handling */ #define CLIT_BIT_FD(x) (clit_bit_fd_p(x) ? (int)(x).z : -1) static inline __attribute__((const, pure)) bool clit_bit_buf_p(clit_bit_t x) { return x.z != -1UL && x.d != NULL; } static inline __attribute__((const, pure)) bool clit_bit_fd_p(clit_bit_t x) { return x.d == NULL; } static inline __attribute__((const, pure)) bool clit_bit_fn_p(clit_bit_t x) { return x.z == -1UL && x.d != NULL; } /* ctors */ static inline __attribute__((unused)) clit_bit_t clit_make_fd(int fd) { return (clit_bit_t){.z = fd}; } static inline clit_bit_t clit_make_fn(const char *fn) { return (clit_bit_t){.z = -1UL, .d = fn}; } static const char* bufexp(const char src[static 1], size_t ssz) { static char *buf; static size_t bsz; wordexp_t xp[1]; if (UNLIKELY(ssz == 0)) { return NULL; } #define CHKBSZ(x) \ if ((x) >= bsz) { \ bsz = ((x) / 256U + 1U) * 256U; \ if (UNLIKELY((buf = realloc(buf, bsz)) == NULL)) { \ /* well we'll leak XP here */ \ return NULL; \ } \ } /* get our own copy for deep vein massages */ CHKBSZ(ssz); memcpy(buf, src, ssz); buf[ssz] = '\0'; switch (wordexp(buf, xp, WRDE_UNDEF)) { case 0: if (xp->we_wordc > 0) { /* everything's fine */ break; } case WRDE_NOSPACE: wordfree(xp); default: return NULL; } /* copy the first `argument', back into BUF, * which is hopefully big enough */ with (size_t wz = strlen(xp->we_wordv[0])) { CHKBSZ(wz); memcpy(buf, xp->we_wordv[0], wz); buf[wz] = '\0'; } wordfree(xp); return buf; } static clitf_t mmap_fd(int fd, size_t fz) { void *p; if ((p = mmap(NULL, fz, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED) { return (clitf_t){.z = 0U, .d = NULL}; } return (clitf_t){.z = fz, .d = p}; } static int munmap_fd(clitf_t map) { return munmap(map.d, map.z); } static void block_sigs(void) { (void)sigprocmask(SIG_BLOCK, fatal_signal_set, (sigset_t*)NULL); return; } static void unblock_sigs(void) { sigprocmask(SIG_SETMASK, empty_signal_set, (sigset_t*)NULL); return; } static void unblock_sig(int sig) { static sigset_t unblk_set[1]; sigemptyset(unblk_set); sigaddset(unblk_set, sig); (void)sigprocmask(SIG_UNBLOCK, unblk_set, (sigset_t*)NULL); return; } #if defined HAVE_PTY_H static pid_t pfork(int *pty) { if (UNLIKELY(pty == NULL)) { errno = ENOMEM; return -1; } return forkpty(pty, NULL, NULL, NULL); } #else /* !HAVE_PTY_H */ static pid_t pfork(int *pty) { fputs("pseudo-tty not supported\n", stderr); return *pty = -1; } #endif /* HAVE_PTY_H */ static inline int xsplice(int tgtfd, int srcfd, unsigned int flags) { #if defined HAVE_SPLICE && defined __linux__ for (ssize_t nsp; (nsp = splice( srcfd, NULL, tgtfd, NULL, 4096U, flags)) == 4096U;); #else /* !HAVE_SPLICE || !__linux__ */ /* in particular, AIX's splice works on tcp sockets only */ with (char *buf[16U * 4096U]) { ssize_t nrd; while ((nrd = read(srcfd, buf, sizeof(buf))) > 0) { for (ssize_t nwr, totw = 0; totw < nrd && (nwr = write( tgtfd, buf + totw, nrd - totw)) >= 0; totw += nwr); } } #endif /* HAVE_SPLICE && __linux__ */ return 0; } static const char * find_shtok(const char *bp, size_t bz) { /* finds a (lone) occurrence of $ at the beginning of a line */ for (const char *res; (res = memchr(bp, '$', bz)) != NULL; bz -= (res + 1 - bp), bp = res + 1) { /* we're actually after a "\n$" or * a "$" at the beginning of the buffer pointer (bp) * now check that either the buffer ends there or * the $ is followed by a newline, or the $ is followed * by a space, which is the line-to-exec indicator */ if ((res == bp || res[-1] == '\n') && (bz <= 1U || (res[1] == '\n' || res[1] == ' '))) { return res; } } return NULL; } static clit_bit_t find_cmd(const char *bp, size_t bz) { clit_bit_t resbit = {0U}; clit_bit_t tok; /* find the bit where it says '$ ' */ with (const char *res) { if (UNLIKELY((res = find_shtok(bp, bz)) == NULL)) { return (clit_bit_t){0U}; } else if (UNLIKELY(res[1] != ' ')) { return (clit_bit_t){0U}; } /* otherwise */ resbit.d = res += 2U; bz -= res - bp; bp = res; } /* find the new line bit */ for (const char *res; (res = memchr(bp, '\n', bz)) != NULL; bz -= (res + 1U - bp), bp = res + 1U) { size_t lz = (res + 1U - bp); /* check for trailing \ or <cmd.d, *const ec = cmd + tst->cmd.z) { static char tok_ign[] = "ignore"; static char tok_out[] = "output"; static char tok_ret[] = "return"; if (strncmp(cmd, tok_ign, strlenof(tok_ign))) { /* don't bother */ break; } /* fast-forward a little */ cmd += strlenof(tok_ign); if (isspace(*cmd)) { /* it's our famous ignore token it seems */ tst->ign_out = tst->ign_ret = 1U; } else if (*cmd++ != '-') { /* unknown token then */ break; } else if (!strncmp(cmd, tok_out, strlenof(tok_out))) { /* ignore-output it is */ tst->ign_out = 1U; cmd += strlenof(tok_out); } else if (!strncmp(cmd, tok_ret, strlenof(tok_ret))) { /* ignore-return it is */ tst->ign_ret = 1U; cmd += strlenof(tok_ret); } else { /* don't know what's going on */ break; } /* now, fast-forward to the actual command, and reass */ while (++cmd < ec && isspace(*cmd)); tst->cmd.z -= (cmd - tst->cmd.d); tst->cmd.d = cmd; return 0; } return -1; } static int find_negexp(struct clit_tst_s tst[static 1]) { with (const char *cmd = tst->cmd.d, *const ec = cmd + tst->cmd.z) { unsigned int exp = 0U; switch (*cmd) { case '!'/*NEG*/: exp = 255U; break; case '?'/*EXP*/:; char *p; exp = strtoul(cmd + 1U, &p, 10); cmd = p; if (isspace(*cmd)) { break; } default: tst->exp_ret = 0U; return -1; } /* now, fast-forward to the actual command, and reass */ while (++cmd < ec && isspace(*cmd)); tst->cmd.z -= (cmd - tst->cmd.d); tst->cmd.d = cmd; tst->exp_ret = exp; } return 0; } static int find_suppdiff(struct clit_tst_s tst[static 1]) { with (const char *cmd = tst->cmd.d, *const ec = cmd + tst->cmd.z) { switch (*cmd) { case '@': break; default: return -1; } /* now, fast-forward to the actual command, and reass */ while (++cmd < ec && isspace(*cmd)); tst->cmd.z -= (cmd - tst->cmd.d); tst->cmd.d = cmd; tst->supp_diff = 1U; tst->ign_out = 1U; } return 0; } static int find_xpnd_proto(struct clit_tst_s tst[static 1]) { with (const char *cmd = tst->cmd.d, *const ec = cmd + tst->cmd.z) { switch (*cmd) { case '$': break; default: return -1; } /* now, fast-forward to the actual command, and reass */ while (++cmd < ec && isspace(*cmd)); tst->cmd.z -= (cmd - tst->cmd.d); tst->cmd.d = cmd; tst->xpnd_proto = 1U; } return 0; } static int find_tst(struct clit_tst_s tst[static 1], const char *bp, size_t bz) { if (UNLIKELY(!(tst->cmd = find_cmd(bp, bz)).z)) { goto fail; } /* reset bp and bz */ bz = bz - (tst->cmd.d + tst->cmd.z - bp); bp = tst->cmd.d + tst->cmd.z; if (UNLIKELY((tst->rest.d = find_shtok(bp, bz)) == NULL)) { goto fail; } /* otherwise set the rest bit already */ tst->rest.z = bz - (tst->rest.d - bp); /* now the stdout bit must be in between (or 0) */ with (size_t outz = tst->rest.d - bp) { if (outz && /* prefixed '< '? */ UNLIKELY(bp[0] == '<' && bp[1] == ' ')) { /* it's a < FILE comparison */ const char *fn; if ((fn = bufexp(bp + 2, outz - 2U - 1U)) != NULL) { tst->out = clit_make_fn(fn); } else { error("expansion failed"); goto fail; } } else { tst->out = (clit_bit_t){.z = outz, bp}; } } /* oh let's see if we should ignore things */ (void)find_ignore(tst); /* check for suppress diff */ (void)find_suppdiff(tst); /* check for expect and negate operators */ (void)find_negexp(tst); /* check for proto-output expander */ (void)find_xpnd_proto(tst); tst->err = (clit_bit_t){0U}; return 0; fail: memset(tst, 0, sizeof(*tst)); return -1; } static struct clit_opt_s find_opt(struct clit_opt_s options, const char *bp, size_t bz) { static const char magic[] = "setopt "; for (const char *mp; (mp = xmemmem(bp, bz, magic, strlenof(magic))) != NULL; bz -= (mp + 1U) - bp, bp = mp + 1U) { unsigned int opt; /* check if it's setopt or unsetopt */ if (mp == bp || LIKELY(mp[-1] == '\n')) { /* yay, it's a genuine setopt */ opt = 1U; } else if (mp >= bp + 2U && mp[-2] == 'u' && mp[-1] == 'n' && (mp == bp + 2U || mp > bp + 2U && mp[-3] == '\n')) { /* it's a genuine unsetopt */ opt = 0U; } else { /* found rubbish then */ mp += strlenof(magic); continue; } #define CMP(x, lit) (strncmp((x), (lit), strlenof(lit))) /* parse the option value */ mp += strlenof(magic); if (NULL) { /* not reached */ ; } else if (CMP(mp, "verbose\n") == 0) { options.verbosep = opt; } else if (CMP(mp, "pseudo-tty\n") == 0) { options.ptyp = opt; } else if (CMP(mp, "timeout") == 0) { const char *arg = mp + sizeof("timeout"); char *p; long unsigned int timeo; if ((timeo = strtoul(arg, &p, 0), *p == '\n')) { options.timeo = (unsigned int)timeo; } } else if (CMP(mp, "keep-going\n") == 0) { options.keep_going_p = opt; } else if (CMP(mp, "shell") == 0) { const char *arg = mp + sizeof("shell"); char *eol = memchr(arg, '\n', bz - (arg - mp)); if (UNLIKELY(eol == NULL)) { /* ignore and get on with it */ continue; } options.shcmd = xstrndup(arg, eol - arg); options.shcmdp = 1U; } else if (CMP(mp, "exit-code") == 0) { const char *arg = mp + sizeof("exit-code"); char *p; long unsigned int xc; if ((xc = strtoul(arg, &p, 0), *p == '\n')) { options.xcod = (unsigned int)xc; } } #undef CMP } return options; } static int init_chld(struct clit_chld_s ctx[static 1] __attribute__((unused))) { /* set up the set of fatal signals */ sigemptyset(fatal_signal_set); sigaddset(fatal_signal_set, SIGHUP); sigaddset(fatal_signal_set, SIGQUIT); sigaddset(fatal_signal_set, SIGINT); sigaddset(fatal_signal_set, SIGTERM); sigaddset(fatal_signal_set, SIGXCPU); sigaddset(fatal_signal_set, SIGXFSZ); /* also the empty set */ sigemptyset(empty_signal_set); /* cmdify the shell command, if any */ if (ctx->options.shcmd != NULL) { ctx->huskv = cmdify(ctx->options.shcmd); } return 0; } static int fini_chld(struct clit_chld_s ctx[static 1]) { if (ctx->huskv != NULL) { free(ctx->huskv); } if (ctx->options.shcmdp) { free(ctx->options.shcmd); } return 0; } static char* mkfifofn(const char *key, unsigned int tid) { size_t len = strlen(key) + 9U + 8U + 1U; char *buf; if (UNLIKELY((buf = malloc(len)) == NULL)) { return NULL; } redo: /* otherwise generate a name for use as fifo */ snprintf(buf, len, "%s output %x", key, tid); if (mkfifo(buf, 0666) < 0) { switch (errno) { case EEXIST: /* try and generate a different name */ tid++; goto redo; default: free(buf); buf = NULL; break; } } return buf; } static pid_t feeder(clit_bit_t exp, int expfd) { pid_t feed; switch ((feed = fork())) { case -1: /* ah good then */ break; case 0:; /* i am the child */ ssize_t nwr; while (exp.z > 0 && (nwr = write(expfd, exp.d, exp.z)) > 0) { exp.d += nwr; if ((size_t)nwr <= exp.z) { exp.z -= nwr; } else { exp.z = 0; } } /* we're done */ close(expfd); /* and out, always succeed */ exit(EXIT_SUCCESS); default: /* i'm the parent */ break; } return feed; } static pid_t xpnder(clit_bit_t exp, int expfd) { pid_t feed; switch ((feed = fork())) { case -1: /* ah good then */ break; case 0:; /* i am the child */ ssize_t nwr; int xin[2U]; pid_t sh; if (UNLIKELY(pipe(xin) < 0)) { fail: /* whatever */ exit(EXIT_FAILURE); } switch ((sh = fork())) { static char *const sh_args[] = {"sh", "-s", NULL}; case -1: /* big fucking problem */ goto fail; case 0: /* close write end of pipe */ close(xin[1U]); /* redir xin[0U] -> stdin */ dup2(xin[0U], STDIN_FILENO); /* close read end of pipe */ close(xin[0U]); /* redir stdout -> expfd */ dup2(expfd, STDOUT_FILENO); /* close expfd */ close(expfd); /* child again */ execv("/bin/sh", sh_args); exit(EXIT_SUCCESS); default: /* parent i am */ close(xin[0U]); /* also forget about expfd */ close(expfd); break; } if (write(xin[1U], "cat < 0 && (nwr = write(xin[1U], exp.d, exp.z)) > 0) { exp.d += nwr; if ((size_t)nwr <= exp.z) { exp.z -= nwr; } else { exp.z = 0; } } if (write(xin[1U], "EOF\n", 4U) < 4) { goto fail; } /* we're done */ close(xin[1U]); /* wait for child process */ with (int st) { while (waitpid(sh, &st, 0) != sh); } /* and out, always succeed */ exit(EXIT_SUCCESS); default: /* i'm the parent */ break; } return feed; } static pid_t differ(struct clit_chld_s ctx[static 1], clit_bit_t exp, bool xpnd_proto_p) { char *expfn = NULL; char *actfn = NULL; pid_t difftool = -1; unsigned int test_id; assert(!clit_bit_fd_p(exp)); /* obtain a test id */ with (struct timeval tv[1]) { (void)gettimeofday(tv, NULL); test_id = (unsigned int)(tv->tv_sec ^ tv->tv_usec); } if (clit_bit_fn_p(exp)) { expfn = malloc(strlen(exp.d) + 1U); if (UNLIKELY(expfn == NULL || strcpy(expfn, exp.d) == NULL)) { error("cannot prepare file `%s'", exp.d); goto out; } } else { expfn = mkfifofn("expected", test_id); if (expfn == NULL) { error("cannot create fifo `%s'", expfn); goto out; } } actfn = mkfifofn("actual", test_id); if (actfn == NULL) { error("cannot create fifo `%s'", actfn); goto out; } block_sigs(); switch ((difftool = vfork())) { case -1: /* i am an error */ error("vfork for diff failed"); break; case 0: { /* i am the child */ char *const diff_opt[] = { "diff", "-u", expfn, actfn, NULL, }; unblock_sigs(); /* don't allow input at all */ close(STDIN_FILENO); /* diff stdout -> stderr */ dup2(STDERR_FILENO, STDOUT_FILENO); execvp(cmd_diff, diff_opt); /* just unlink the files the WRONLY is waiting for * ACTFN is always something that we create and unlink, * so delete that one now to trigger an error in the * parent's open() code below */ unlink(actfn); /* EXPFN is opened in the parent code below if it's * a fifo created by us, unlink that one to break the hang */ if (clit_bit_buf_p(exp)) { unlink(expfn); } _exit(EXIT_FAILURE); } default:; /* i am the parent */ static const int ofl = O_WRONLY; int expfd = -1; int actfd = -1; /* clean up descriptors */ if (clit_bit_buf_p(exp) && (expfd = open(expfn, ofl, 0666)) < 0) { goto clobrk; } else if ((actfd = open(actfn, ofl, 0666)) < 0) { goto clobrk; } /* assign actfd as out descriptor */ ctx->pou = actfd; /* fork out the feeder guy */ if (clit_bit_buf_p(exp)) { /* check if we need the expander */ if (LIKELY(!xpnd_proto_p)) { ctx->feed = feeder(exp, expfd); } else { ctx->feed = xpnder(exp, expfd); } /* forget about expfd lest we leak it */ close(expfd); } else { /* best to let everyone know that we chose * not to use a feeder */ ctx->feed = -1; } break; clobrk: error("exec'ing %s failed", cmd_diff); if (expfd >= 0) { close(expfd); } kill(difftool, SIGTERM); difftool = -1; break; } unblock_sigs(); out: if (expfn) { if (!clit_bit_fn_p(exp)) { unlink(expfn); } free(expfn); } if (actfn) { unlink(actfn); free(actfn); } return difftool; } static int init_tst(struct clit_chld_s ctx[static 1], struct clit_tst_s tst[static 1]) { /* set up a connection with /bin/sh to pipe to and read from */ int pty; int pin[2]; int per[2]; if (!tst->supp_diff) { ctx->diff = differ(ctx, tst->out, tst->xpnd_proto); } else { ctx->diff = -1; ctx->feed = -1; ctx->pou = -1; } if (0) { ; } else if (UNLIKELY(pipe(pin) < 0)) { ctx->chld = -1; return -1; } else if (UNLIKELY(ctx->options.ptyp && pipe(per) < 0)) { ctx->chld = -1; return -1; } block_sigs(); switch ((ctx->chld = !ctx->options.ptyp ? vfork() : pfork(&pty))) { case -1: /* i am an error */ unblock_sigs(); return -1; case 0: /* i am the child */ unblock_sigs(); if (UNLIKELY(ctx->options.ptyp)) { /* in pty mode connect child's stderr to parent's */ ; } /* read from pin and write to pou */ if (LIKELY(!ctx->options.ptyp)) { /* pin[0] ->stdin */ dup2(pin[0], STDIN_FILENO); } else { dup2(per[1], STDERR_FILENO); close(per[0]); close(per[1]); } close(pin[0]); close(pin[1]); /* stdout -> pou[1] */ if (!tst->supp_diff) { dup2(ctx->pou, STDOUT_FILENO); close(ctx->pou); } if (!ctx->huskv) { execl("/bin/sh", "sh", NULL); } else { execvp(*ctx->huskv, ctx->huskv); } error("exec'ing /bin/sh failed"); _exit(EXIT_FAILURE); default: /* i am the parent, clean up descriptors */ close(pin[0]); if (UNLIKELY(ctx->options.ptyp)) { close(pin[1]); } if (LIKELY(ctx->pou >= 0)) { close(ctx->pou); } ctx->pou = -1; /* assign desc, write end of pin */ if (LIKELY(!ctx->options.ptyp)) { ctx->pin = pin[1]; } else { ctx->pin = pty; ctx->per = per[0]; close(per[1]); } break; } return 0; } static struct { void (*old_hdl)(int); pid_t feed; pid_t diff; } alrm_handler_closure; static void alrm_handler(int signum) { assert(signum == SIGALRM); if (alrm_handler_closure.feed > 0) { kill(alrm_handler_closure.feed, SIGALRM); } if (alrm_handler_closure.diff > 0) { kill(alrm_handler_closure.diff, SIGALRM); } signal(SIGALRM, alrm_handler_closure.old_hdl); with (pid_t self = getpid()) { if (LIKELY(self > 0)) { kill(self, SIGALRM); } } return; } static int run_tst(struct clit_chld_s ctx[static 1], struct clit_tst_s tst[static 1]) { int rc = 0; int st; if (UNLIKELY(init_tst(ctx, tst) < 0)) { rc = -1; if (ctx->feed > 0) { kill(ctx->feed, SIGTERM); } if (ctx->diff > 0) { kill(ctx->diff, SIGTERM); } goto wait; } if (ctx->options.timeo > 0 && (ctx->feed > 0 || ctx->diff > 0)) { alrm_handler_closure.feed = ctx->feed; alrm_handler_closure.diff = ctx->diff; alrm_handler_closure.old_hdl = signal(SIGALRM, alrm_handler); } with (const char *p = tst->cmd.d, *const ep = tst->cmd.d + tst->cmd.z) { for (ssize_t nwr; p < ep && (nwr = write(ctx->pin, p, ep - p)) > 0; p += nwr); } unblock_sigs(); if (LIKELY(!ctx->options.ptyp) || write(ctx->pin, "exit $?\n", 8U) < 8) { /* indicate we're not writing anymore on the child's stdin * or in case of a pty, send exit command and keep fingers * crossed the pty will close itself */ close(ctx->pin); ctx->pin = -1; } /* wait for the beef child */ while (ctx->chld > 0 && waitpid(ctx->chld, &st, 0) != ctx->chld); if (LIKELY(ctx->chld > 0 && WIFEXITED(st))) { rc = WEXITSTATUS(st); if (tst->exp_ret == rc) { rc = 0; } else if (tst->exp_ret == 255U && rc) { rc = 0; } else if (ctx->options.xcod) { rc = ctx->options.xcod; } } else { rc = 1; } wait: /* wait for the feeder */ while (ctx->feed > 0 && waitpid(ctx->feed, &st, 0) != ctx->feed); if (LIKELY(ctx->feed > 0 && WIFEXITED(st))) { int tmp_rc = WEXITSTATUS(st); if (tst->ign_out) { /* don't worry */ ; } else if (tmp_rc > rc) { rc = tmp_rc; } } /* finally wait for the differ */ while (ctx->diff > 0 && waitpid(ctx->diff, &st, 0) != ctx->diff); if (LIKELY(ctx->diff > 0 && WIFEXITED(st))) { int tmp_rc = WEXITSTATUS(st); if (tst->ign_out) { /* don't worry */ ; } else if (tmp_rc > rc) { rc = tmp_rc; } } /* and after all, if we ignore the rcs just reset them to zero */ if (tst->ign_ret) { rc = 0; } #if defined HAVE_PTY_H if (UNLIKELY(ctx->options.ptyp && ctx->pin >= 0)) { /* also close child's stdin here */ close(ctx->pin); } /* also connect per's out end with stderr */ if (UNLIKELY(ctx->options.ptyp)) { xsplice(ctx->per, STDERR_FILENO, SPLICE_F_MOVE); close(ctx->per); } #endif /* HAVE_PTY_H */ if (ctx->options.timeo > 0 && (ctx->feed > 0 || ctx->diff > 0)) { signal(SIGALRM, alrm_handler_closure.old_hdl); } return rc; } static void set_timeout(unsigned int tdiff) { if (UNLIKELY(tdiff == 0U)) { return; } /* unblock just this one signal */ unblock_sig(SIGALRM); alarm(tdiff); return; } static void prepend_path(const char *p) { #define free_path() prepend_path(NULL); static char *paths; static size_t pathz; static char *restrict pp; size_t pz; if (UNLIKELY(p == NULL)) { /* freeing */ if (paths == NULL) { free(paths); paths = pp = NULL; } return; } /* otherwise it'd be safe to compute the strlen() methinks */ pz = strlen(p); if (UNLIKELY(paths == NULL)) { char *envp; if (LIKELY((envp = getenv("PATH")) != NULL)) { const size_t envz = strlen(envp); /* get us a nice big cushion */ pathz = ((envz + pz + 1U/*\nul*/) / 256U + 2U) * 256U; if (UNLIKELY((paths = malloc(pathz)) == NULL)) { /* don't bother then */ return; } /* set pp for further reference */ pp = (paths + pathz) - (envz + 1U/*\nul*/); /* glue the current path at the end of the array */ memccpy(pp, envp, '\0', envz); /* terminate pp at least at the very end */ pp[envz] = '\0'; } else { /* just alloc space for P */ pathz = ((pz + 1U/*\nul*/) / 256U + 2U) * 256U; if (UNLIKELY((paths = malloc(pathz)) == NULL)) { /* don't bother then */ return; } /* set pp for further reference */ pp = (paths + pathz) - (pz + 1U/*\nul*/); /* copy P and then exit */ memcpy(pp, p, pz + 1U/*\nul*/); goto out; } } /* calc prepension pointer */ pp -= pz + 1U/*:*/; if (UNLIKELY(pp < paths)) { /* awww, not enough space, is there */ ptrdiff_t ppoff = pp - paths; size_t newsz = ((pathz + pz + 1U/*:*/) / 256U + 1U) * 256U; if (UNLIKELY((paths = realloc(paths, newsz)) == NULL)) { /* just leave things be */ return; } /* memmove to the back */ memmove(paths + (newsz - pathz), paths, pathz); /* recalc paths pointer */ pp = paths + (newsz - pathz) + ppoff; pathz = newsz; } /* actually prepend now */ memcpy(pp, p, pz); pp[pz] = ':'; out: setenv("PATH", pp, 1); return; } static int test_f(clitf_t tf, struct clit_opt_s options) { static struct clit_chld_s ctx[1]; static struct clit_tst_s tst[1]; const char *bp = tf.d; size_t bz = tf.z; int rc = 0; /* find options in the test script or from the proto */ ctx->options = find_opt(options, bp, bz); if (UNLIKELY(init_chld(ctx) < 0)) { return -1; } /* prepare */ if (ctx->options.timeo > 0) { set_timeout(ctx->options.timeo); } for (; find_tst(tst, bp, bz) == 0; bp = tst->rest.d, bz = tst->rest.z) { if (ctx->options.verbosep) { fputs("$ ", stderr); fwrite(tst->cmd.d, sizeof(char), tst->cmd.z, stderr); } with (int tst_rc = run_tst(ctx, tst)) { if (ctx->options.verbosep) { fprintf(stderr, "$? %d\n", tst_rc); } rc = rc ?: tst_rc; } if (rc && !ctx->options.keep_going_p) { break; } } if (UNLIKELY(fini_chld(ctx)) < 0) { rc = -1; } return rc; } static int test(const char *testfile, struct clit_opt_s options) { int fd; struct stat st; clitf_t tf; int rc = -1; if ((fd = open(testfile, O_RDONLY)) < 0) { error("Error: cannot open file `%s'", testfile); goto out; } else if (fstat(fd, &st) < 0) { error("Error: cannot stat file `%s'", testfile); goto clo; } else if ((tf = mmap_fd(fd, st.st_size)).d == NULL) { error("Error: cannot map file `%s'", testfile); goto clo; } /* yaay, perform the test */ rc = test_f(tf, options); /* and out we are */ munmap_fd(tf); clo: close(fd); out: return rc; } #include "clitosis.yucc" int main(int argc, char *argv[]) { static const char *const ends[] = { [CLIT_END_UNKNOWN] = "unknown", [CLIT_END_BIG] = "big", [CLIT_END_LITTLE] = "little", [CLIT_END_MIDDLE] = "middle", }; yuck_t argi[1U]; struct clit_opt_s options = {0U}; int rc = 99; if (yuck_parse(argi, argc, argv)) { goto out; } else if (argi->nargs != 1U) { yuck_auto_help(argi); goto out; } if (argi->builddir_arg) { setenv("builddir", argi->builddir_arg, 1); } if (argi->srcdir_arg) { setenv("srcdir", argi->srcdir_arg, 1); } if (argi->shell_arg) { options.shcmd = argi->shell_arg; } if (argi->verbose_flag) { options.verbosep = 1U; } if (argi->pseudo_tty_flag) { options.ptyp = 1U; } if (argi->timeout_arg) { options.timeo = strtoul(argi->timeout_arg, NULL, 10); } if (argi->keep_going_flag) { options.keep_going_p = 1U; } if (argi->diff_arg) { cmd_diff = argi->diff_arg; } else if (getenv("DIFF") != NULL) { cmd_diff = getenv("DIFF"); } if (argi->exit_code_arg == (const char*)0x1U) { options.xcod = 0U; } else if (argi->exit_code_arg) { options.xcod = strtoul(argi->exit_code_arg, NULL, 0); } else { options.xcod = 1U; } /* Although I cannot support my claim with a hard survey, I would * say in 99.9 cases out of a hundred the cli tool in question * has not been installed at the time of testing it, so somehow * we must make sure to test the version in the build directory * rather than a globally installed one. * * On the other hand, in general we won't know where the build * directory is, we've got --builddir for that, however we can * assist our users by prepending the current working directory * and the directory we're run from to PATH. * * So let's prepend our argv[0] directory */ with (char *arg0 = get_argv0dir(argv[0])) { if (LIKELY(arg0 != NULL)) { prepend_path(arg0); free_argv0dir(arg0); } } /* ... and our current directory */ prepend_path("."); /* also bang builddir to path */ with (char *blddir = getenv("builddir")) { if (LIKELY(blddir != NULL)) { /* use at most 256U bytes for blddir */ char _blddir[256U]; memccpy(_blddir, blddir, '\0', strlenof(_blddir)); _blddir[strlenof(_blddir)] = '\0'; prepend_path(_blddir); } } /* just to be clear about this */ setenv("endian", ends[get_endianness()], 1); if ((rc = test(argi->args[0U], options)) < 0) { rc = 99; } /* resource freeing */ free_path(); out: yuck_free(argi); return rc; } /* clitosis.c ends here */ dateutils-0.4.5/test/clitosis.yuck000066400000000000000000000013631335042257000172270ustar00rootroot00000000000000Usage: clitoris [OPTION]... TEST_FILE Run .clit regression test files. --builddir=DIR Specify where the compiled binaries can be found. --srcdir=DIR Specify where the source tree resides. --shell=CMD Use CMD as shell command, default: /bin/sh -v, --verbose Repeat execution steps on stderr. -t, --pseudo-tty Allocate a pseudo-tty for the tests to run in. --timeout=SECS Time out after SECS seconds. -k, --keep-going Don't break on the first failure or differing output --diff=CMD Use specified diff command instead of the one in PATH. -x, --exit-code[=N] Map any non-0 exit code from the commands to N, (default: 1), or, if N is omitted, pass the exit code through as is. dateutils-0.4.5/test/convt.yd-ymcw.clit000066400000000000000000000003601335042257000200730ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq "1917-01-01" "2399-12-31" -f "yd" > "convt.yd-ymcw.ref" $ dconv -f "ymcw" < "convt.yd-ymcw.ref" | dconv -f "yd" < "convt.yd-ymcw.ref" $ rm -- "convt.yd-ymcw.ref" $ ## convt.yd-ymcw.clit dateutils-0.4.5/test/convt.yd-ymd.clit000066400000000000000000000003521335042257000177060ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq "1917-01-01" "2399-12-31" -f "yd" > "convt.yd-ymd.ref" $ dconv -f "ymd" < "convt.yd-ymd.ref" | dconv -f "yd" < "convt.yd-ymd.ref" $ rm -- "convt.yd-ymd.ref" $ ## convt.yd-ymd.clit dateutils-0.4.5/test/convt.yd-ywd.clit000066400000000000000000000003521335042257000177200ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq "1917-01-01" "2399-12-31" -f "yd" > "convt.yd-ywd.ref" $ dconv -f "ywd" < "convt.yd-ywd.ref" | dconv -f "yd" < "convt.yd-ywd.ref" $ rm -- "convt.yd-ywd.ref" $ ## convt.yd-ywd.clit dateutils-0.4.5/test/convt.ymcw-yd.clit000066400000000000000000000003621335042257000200750ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq "1917-01-01" "2399-12-31" -f "ymcw" > "convt.ymcw-yd.ref" $ dconv -f "yd" < "convt.ymcw-yd.ref" | dconv -f "ymcw" < "convt.ymcw-yd.ref" $ rm -- "convt.ymcw-yd.ref" $ ## convt.ymcw-yd.clit dateutils-0.4.5/test/convt.ymcw-ymd.clit000066400000000000000000000003701335042257000202510ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq "1917-01-01" "2399-12-31" -f "ymcw" > "convt.ymcw-ymd.ref" $ dconv -f "ymd" < "convt.ymcw-ymd.ref" | dconv -f "ymcw" < "convt.ymcw-ymd.ref" $ rm -- "convt.ymcw-ymd.ref" $ ## convt.ymcw-ymd.clit dateutils-0.4.5/test/convt.ymcw-ywd.clit000066400000000000000000000003701335042257000202630ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq "1917-01-01" "2399-12-31" -f "ymcw" > "convt.ymcw-ywd.ref" $ dconv -f "ywd" < "convt.ymcw-ywd.ref" | dconv -f "ymcw" < "convt.ymcw-ywd.ref" $ rm -- "convt.ymcw-ywd.ref" $ ## convt.ymcw-ywd.clit dateutils-0.4.5/test/convt.ymd-yd.clit000066400000000000000000000003531335042257000177070ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq "1917-01-01" "2399-12-31" -f "ymd" > "convt.ymd-yd.ref" $ dconv -f "yd" < "convt.ymd-yd.ref" | dconv -f "ymd" < "convt.ymd-yd.ref" $ rm -- "convt.ymd-yd.ref" $ ## convt.ymd-yd.clit dateutils-0.4.5/test/convt.ymd-ymcw.clit000066400000000000000000000003671335042257000202570ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq "1917-01-01" "2399-12-31" -f "ymd" > "convt.ymd-ymcw.ref" $ dconv -f "ymcw" < "convt.ymd-ymcw.ref" | dconv -f "ymd" < "convt.ymd-ymcw.ref" $ rm -- "convt.ymd-ymcw.ref" $ ## convt.ymd-ymcw.clit dateutils-0.4.5/test/convt.ymd-ywd.clit000066400000000000000000000003611335042257000200750ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq "1917-01-01" "2399-12-31" -f "ymd" > "convt.ymd-ywd.ref" $ dconv -f "ywd" < "convt.ymd-ywd.ref" | dconv -f "ymd" < "convt.ymd-ywd.ref" $ rm -- "convt.ymd-ywd.ref" $ ## convt.ymd-ywd.clit dateutils-0.4.5/test/convt.ywd-yd.clit000066400000000000000000000003531335042257000177210ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq "1917-01-01" "2399-12-31" -f "ywd" > "convt.ywd-yd.ref" $ dconv -f "yd" < "convt.ywd-yd.ref" | dconv -f "ywd" < "convt.ywd-yd.ref" $ rm -- "convt.ywd-yd.ref" $ ## convt.ywd-yd.clit dateutils-0.4.5/test/convt.ywd-ymcw.clit000066400000000000000000000003671335042257000202710ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq "1917-01-01" "2399-12-31" -f "ywd" > "convt.ywd-ymcw.ref" $ dconv -f "ymcw" < "convt.ywd-ymcw.ref" | dconv -f "ywd" < "convt.ywd-ymcw.ref" $ rm -- "convt.ywd-ymcw.ref" $ ## convt.ywd-ymcw.clit dateutils-0.4.5/test/convt.ywd-ymd.clit000066400000000000000000000003611335042257000200750ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq "1917-01-01" "2399-12-31" -f "ywd" > "convt.ywd-ymd.ref" $ dconv -f "ymd" < "convt.ywd-ymd.ref" | dconv -f "ywd" < "convt.ywd-ymd.ref" $ rm -- "convt.ywd-ymd.ref" $ ## convt.ywd-ymd.clit dateutils-0.4.5/test/dadd.001.clit000066400000000000000000000001541335042257000165460ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dadd 2012-03-01 1d 2012-03-02 $ ## dadd.001.clit ends here dateutils-0.4.5/test/dadd.002.clit000066400000000000000000000001551335042257000165500ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dadd 2012-03-01 1mo 2012-04-01 $ ## dadd.002.clit ends here dateutils-0.4.5/test/dadd.003.clit000066400000000000000000000001551335042257000165510ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dadd 2012-03-31 1mo 2012-04-30 $ ## dadd.003.clit ends here dateutils-0.4.5/test/dadd.004.clit000066400000000000000000000003201335042257000165440ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dadd 2w2d < "${foo}" for y in `seq ${BEG} ${END}`; do TZ=UTC LANG=C LC_ALL=C "${GDATE}" -d "${y}-01-01" '+%F %a' done > "${bar}" diff "${foo}" "${bar}" rc=${?} rm -f "${foo}" "${bar}" exit ${rc} dateutils-0.4.5/test/dconv-batch.2.sh000077500000000000000000000010671335042257000173710ustar00rootroot00000000000000#!/bin/sh BEG="1917" END="4095" if test "${have_gdate_2039}" != "yes"; then BEG="1970" END="2037" fi if test "${have_gdate}" != "yes"; then ## SKIP in new automake exit 77 fi TOOLDIR="$(pwd)/../src" DCONV="${TOOLDIR}/dconv" foo=`mktemp "/tmp/tmp.XXXXXXXXXX"` bar=`mktemp "/tmp/tmp.XXXXXXXXXX"` for y in `seq ${BEG} ${END}`; do "${DCONV}" "${y}-12-31" -f '%F %a' done > "${foo}" for y in `seq ${BEG} ${END}`; do TZ=UTC LANG=C LC_ALL=C "${GDATE}" -d "${y}-12-31" '+%F %a' done > "${bar}" diff "${foo}" "${bar}" rc=${?} rm -f "${foo}" "${bar}" exit ${rc} dateutils-0.4.5/test/dconv.001.clit000066400000000000000000000001511335042257000167600ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dconv 2012-03-01 2012-03-01 $ ## dconv.1.clit ends here dateutils-0.4.5/test/dconv.002.clit000066400000000000000000000001661335042257000167670ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dconv -i "%d/%b/%y" 01/Mar/12 2012-03-01 $ ## dconv.2.clit ends here dateutils-0.4.5/test/dconv.003.clit000066400000000000000000000001661335042257000167700ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dconv -f "%d/%b/%y" 2012-03-01 01/Mar/12 $ ## dconv.3.clit ends here dateutils-0.4.5/test/dconv.004.clit000066400000000000000000000002201335042257000167600ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dconv -f "%d/%b/%y" -i "%OY %Om %Od" "MCMXCVIII IX XVII" 17/Sep/98 $ ## dconv.4.clit ends here dateutils-0.4.5/test/dconv.005.clit000066400000000000000000000002161335042257000167660ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dconv -i "%d/%b/%y" -f "%OY %Om %Od" 17/Sep/98 MCMXCVIII IX XVII $ ## dconv.5.clit ends here dateutils-0.4.5/test/dconv.006.clit000066400000000000000000000001671335042257000167740ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dconv -f "%Y-%jb" "2010-03-01b" 2010-042b $ ## dconv.6.clit ends here dateutils-0.4.5/test/dconv.007.clit000066400000000000000000000001671335042257000167750ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dconv -f "%Y-%jb" "2012-03-02b" 2012-045b $ ## dconv.7.clit ends here dateutils-0.4.5/test/dconv.008.clit000066400000000000000000000001671335042257000167760ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dconv -f "%Y-%jb" "2012-05-02b" 2012-088b $ ## dconv.8.clit ends here dateutils-0.4.5/test/dconv.009.clit000066400000000000000000000043341335042257000167770ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dconv -f "ymd" -S -i "%d/%b/%Y" <2012-03-01 <=2012-03-01 <=2012-11-01' -i "%B/%d/%y" <2012-03-01 <=2012-03-01 <=2012-11-01' -i "%B/%d/%y" < "${foo}" ## strip month and dom from BEG and END in a way that works on dash BEG=`echo ${BEG} | sed 's/-.*//'` END=`echo ${END} | sed 's/-.*//'` for y in `seq ${BEG} ${END}`; do TZ=UTC LANG=C LC_ALL=C "${GDATE}" -d "${y}-01-01" '+%F %a' done > "${bar}" diff "${foo}" "${bar}" rc=${?} rm -f "${foo}" "${bar}" exit ${rc} dateutils-0.4.5/test/dseq-cnt.3.sh000077500000000000000000000012671335042257000167220ustar00rootroot00000000000000#!/bin/sh BEG="1917-12-31" END="4095-12-31" if test "${have_gdate_2039}" != "yes"; then BEG="1970-12-31" END="2037-12-31" fi if test "${have_gdate}" != "yes"; then ## SKIP in new automake exit 77 fi TOOLDIR="$(pwd)/../src" DSEQ="${TOOLDIR}/dseq" foo=`mktemp "/tmp/tmp.XXXXXXXXXX"` bar=`mktemp "/tmp/tmp.XXXXXXXXXX"` "${DSEQ}" "${BEG}" +1y "${END}" -f '%F %a' > "${foo}" ## strip month and dom from BEG and END in a way that works on dash BEG=`echo ${BEG} | sed 's/-.*//'` END=`echo ${END} | sed 's/-.*//'` for y in `seq ${BEG} ${END}`; do TZ=UTC LANG=C LC_ALL=C "${GDATE}" -d "${y}-12-31" '+%F %a' done > "${bar}" diff "${foo}" "${bar}" rc=${?} rm -f "${foo}" "${bar}" exit ${rc} dateutils-0.4.5/test/dseq.01.clit000066400000000000000000000006611335042257000165310ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 2012-02-01 2012-03-01 2012-02-01 2012-02-02 2012-02-03 2012-02-04 2012-02-05 2012-02-06 2012-02-07 2012-02-08 2012-02-09 2012-02-10 2012-02-11 2012-02-12 2012-02-13 2012-02-14 2012-02-15 2012-02-16 2012-02-17 2012-02-18 2012-02-19 2012-02-20 2012-02-21 2012-02-22 2012-02-23 2012-02-24 2012-02-25 2012-02-26 2012-02-27 2012-02-28 2012-02-29 2012-03-01 $ ## dseq.1.clit ends here dateutils-0.4.5/test/dseq.02.clit000066400000000000000000000007451335042257000165350ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 2001-02-03 2001-03-03 --skip sat -f "%F %a" 2001-02-04 Sun 2001-02-05 Mon 2001-02-06 Tue 2001-02-07 Wed 2001-02-08 Thu 2001-02-09 Fri 2001-02-11 Sun 2001-02-12 Mon 2001-02-13 Tue 2001-02-14 Wed 2001-02-15 Thu 2001-02-16 Fri 2001-02-18 Sun 2001-02-19 Mon 2001-02-20 Tue 2001-02-21 Wed 2001-02-22 Thu 2001-02-23 Fri 2001-02-25 Sun 2001-02-26 Mon 2001-02-27 Tue 2001-02-28 Wed 2001-03-01 Thu 2001-03-02 Fri $ ## dseq.2.clit ends here dateutils-0.4.5/test/dseq.03.clit000066400000000000000000000007731335042257000165370ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq --compute-from-last 2001-02-03 1 2001-03-03 --skip sat -f "%F %a" 2001-02-04 Sun 2001-02-05 Mon 2001-02-06 Tue 2001-02-07 Wed 2001-02-08 Thu 2001-02-09 Fri 2001-02-11 Sun 2001-02-12 Mon 2001-02-13 Tue 2001-02-14 Wed 2001-02-15 Thu 2001-02-16 Fri 2001-02-18 Sun 2001-02-19 Mon 2001-02-20 Tue 2001-02-21 Wed 2001-02-22 Thu 2001-02-23 Fri 2001-02-25 Sun 2001-02-26 Mon 2001-02-27 Tue 2001-02-28 Wed 2001-03-01 Thu 2001-03-02 Fri $ ## dseq.3.clit ends here dateutils-0.4.5/test/dseq.04.clit000066400000000000000000000003351335042257000165320ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 2001-02-03 3 2001-03-03 --skip sat,fri -f "%F %a" 2001-02-06 Tue 2001-02-12 Mon 2001-02-15 Thu 2001-02-18 Sun 2001-02-21 Wed 2001-02-27 Tue $ ## dseq.4.clit ends here dateutils-0.4.5/test/dseq.05.clit000066400000000000000000000004001335042257000165240ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq --compute-from-last 2001-02-03 3 2001-03-03 --skip sat,fri -f "%F %a" 2001-02-04 Sun 2001-02-07 Wed 2001-02-13 Tue 2001-02-19 Mon 2001-02-22 Thu 2001-02-25 Sun 2001-02-28 Wed $ ## dseq.5.clit ends here dateutils-0.4.5/test/dseq.06.clit000066400000000000000000000003351335042257000165340ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 2001-02-05 4 2001-03-04 -f "%F %a" 2001-02-05 Mon 2001-02-09 Fri 2001-02-13 Tue 2001-02-17 Sat 2001-02-21 Wed 2001-02-25 Sun 2001-03-01 Thu $ ## dseq.6.clit ends here dateutils-0.4.5/test/dseq.07.clit000066400000000000000000000003611335042257000165340ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq --compute-from-last 2001-02-05 4 2001-03-04 -f "%F %a" 2001-02-08 Thu 2001-02-12 Mon 2001-02-16 Fri 2001-02-20 Tue 2001-02-24 Sat 2001-02-28 Wed 2001-03-04 Sun $ ## dseq.7.clit ends here dateutils-0.4.5/test/dseq.08.clit000066400000000000000000000004101335042257000165300ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq --alt-inc 1d 2001-02-03 3 2001-03-03 --skip sat,fri -f "%F %a" 2001-02-04 Sun 2001-02-07 Wed 2001-02-11 Sun 2001-02-14 Wed 2001-02-18 Sun 2001-02-21 Wed 2001-02-25 Sun 2001-02-28 Wed $ ## dseq.8.clit ends here dateutils-0.4.5/test/dseq.09.clit000066400000000000000000000004341335042257000165370ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq --compute-from-last --alt-inc 1d 2001-02-03 3 2001-03-03 --skip sat,fri -f "%F %a" 2001-02-04 Sun 2001-02-07 Wed 2001-02-11 Sun 2001-02-14 Wed 2001-02-18 Sun 2001-02-21 Wed 2001-02-25 Sun 2001-02-28 Wed $ ## dseq.9.clit ends here dateutils-0.4.5/test/dseq.10.clit000066400000000000000000000002271335042257000165270ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 2001-01-01 2d 2001-01-08 2001-01-01 2001-01-03 2001-01-05 2001-01-07 $ ## dseq.10.clit ends here dateutils-0.4.5/test/dseq.11.clit000066400000000000000000000002531335042257000165270ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq --compute-from-last 2001-01-01 2d 2001-01-08 2001-01-02 2001-01-04 2001-01-06 2001-01-08 $ ## dseq.11.clit ends here dateutils-0.4.5/test/dseq.12.clit000066400000000000000000000002301335042257000165230ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 2001-01-08 -2d 2001-01-01 2001-01-08 2001-01-06 2001-01-04 2001-01-02 $ ## dseq.12.clit ends here dateutils-0.4.5/test/dseq.13.clit000066400000000000000000000002541335042257000165320ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq --compute-from-last 2001-01-08 -2d 2001-01-01 2001-01-07 2001-01-05 2001-01-03 2001-01-01 $ ## dseq.13.clit ends here dateutils-0.4.5/test/dseq.14.clit000066400000000000000000000002011335042257000165230ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 2001-02-03 -1 2001-03-03 --skip sat -f "%F %a" $ ## dseq.14.clit ends here dateutils-0.4.5/test/dseq.15.clit000066400000000000000000000002051335042257000165300ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 2001-02-03 -3 2001-03-03 --skip sat,fri -f "%F %a" $ ## dseq.15.clit ends here dateutils-0.4.5/test/dseq.16.clit000066400000000000000000000002051335042257000165310ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 2001-02-03 -1 2001-02-03 -f "%F %a" 2001-02-03 Sat $ ## dseq.16.clit ends here dateutils-0.4.5/test/dseq.17.clit000066400000000000000000000002051335042257000165320ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 2001-02-05 -4 2001-02-05 -f "%F %a" 2001-02-05 Mon $ ## dseq.17.clit ends here dateutils-0.4.5/test/dseq.18.clit000066400000000000000000000001661335042257000165410ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 2001-01-08 2d 2001-01-08 2001-01-08 $ ## dseq.18.clit ends here dateutils-0.4.5/test/dseq.19.clit000066400000000000000000000002041335042257000165330ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 2014-01-12 2014-01-13 -f '%rY-%V' 2014-02 2014-03 $ ## dseq.19.clit ends here dateutils-0.4.5/test/dseq.20.clit000066400000000000000000000002041335042257000165230ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 2014-01-12 2014-01-13 -f '%rY-%W' 2014-01 2014-02 $ ## dseq.20.clit ends here dateutils-0.4.5/test/dseq.21.clit000066400000000000000000000002041335042257000165240ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 2014-01-12 2014-01-13 -f '%rY-%U' 2014-02 2014-02 $ ## dseq.21.clit ends here dateutils-0.4.5/test/dseq.22.clit000066400000000000000000000002031335042257000165240ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 2014-01-12 2014-01-13 -f '%G-%V' 2014-02 2014-03 $ ## dseq.22.clit ends here dateutils-0.4.5/test/dseq.23.clit000066400000000000000000000002031335042257000165250ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 2014-01-12 2014-01-13 -f '%G-%W' 2014-01 2014-02 $ ## dseq.23.clit ends here dateutils-0.4.5/test/dseq.24.clit000066400000000000000000000002031335042257000165260ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 2014-01-12 2014-01-13 -f '%G-%U' 2014-02 2014-02 $ ## dseq.24.clit ends here dateutils-0.4.5/test/dseq.25.clit000066400000000000000000000003071335042257000165340ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 2014-08-18 2014-08-25 -f ywd 2014-W34-1 2014-W34-2 2014-W34-3 2014-W34-4 2014-W34-5 2014-W34-6 2014-W34-7 2014-W35-1 $ ## dseq.25.clit ends here dateutils-0.4.5/test/dseq.26.clit000066400000000000000000000003401335042257000165320ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 2014-08-18 2014-08-25 -f ymcw 2014-08-03-01 2014-08-03-02 2014-08-03-03 2014-08-03-04 2014-08-04-05 2014-08-04-06 2014-08-04-00 2014-08-04-01 $ ## dseq.26.clit ends here dateutils-0.4.5/test/dseq.27.clit000066400000000000000000000001721335042257000165360ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- ## range is empty $ dseq 2001-02-03 2001-02-01 $ ## dseq.27.clit ends here dateutils-0.4.5/test/dseq.28.clit000066400000000000000000000001751335042257000165420ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- ## range is empty $ dseq 2001-02-01 -1 2001-02-04 $ ## dseq.28.clit ends here dateutils-0.4.5/test/dseq.29.clit000066400000000000000000000003051335042257000165360ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 2012-02 2012-09 -i '%Y-%m' 2012-02-00 2012-03-00 2012-04-00 2012-05-00 2012-06-00 2012-07-00 2012-08-00 2012-09-00 $ ## dseq.29.clit ends here dateutils-0.4.5/test/dseq.30.clit000066400000000000000000000003001335042257000165210ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 2012-02-00 2012-09-00 2012-02-00 2012-03-00 2012-04-00 2012-05-00 2012-06-00 2012-07-00 2012-08-00 2012-09-00 $ ## dseq.30.clit ends here dateutils-0.4.5/test/dseq.31.clit000066400000000000000000000002201335042257000165230ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 2012 2015 -i '%Y' 2012-00-00 2013-00-00 2014-00-00 2015-00-00 $ ## dseq.31.clit ends here dateutils-0.4.5/test/dseq.32.clit000066400000000000000000000002241335042257000165300ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 2012-00-00 2015-00-00 2012-00-00 2013-00-00 2014-00-00 2015-00-00 $ ## dseq.32.clit ends here dateutils-0.4.5/test/dseq.33.clit000066400000000000000000000003041335042257000165300ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 2018-01-01 2018-12-30 -f ywd > "dseq.33.ref" $ dseq 2018-W01-1 2018-W52-07 < dseq.33.ref $ rm -f -- "dseq.33.ref" $ ## dseq.33.clit ends here dateutils-0.4.5/test/dseq.34.clit000066400000000000000000000003141335042257000165320ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 2018-01-01 2018-12-30 | dconv -f ywd > "dseq.34.ref" $ dseq 2018-W01-1 2018-W52-07 < dseq.34.ref $ rm -f -- "dseq.34.ref" $ ## dseq.34.clit ends here dateutils-0.4.5/test/dseq.35.clit000066400000000000000000000003041335042257000165320ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 2018-W01-1 2018-W52-07 -f ymd > "dseq.35.ref" $ dseq 2018-01-01 2018-12-30 < dseq.35.ref $ rm -f -- "dseq.35.ref" $ ## dseq.35.clit ends here dateutils-0.4.5/test/dseq.36.clit000066400000000000000000000003141335042257000165340ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 2018-W01-1 2018-W52-07 | dconv -f ymd > "dseq.36.ref" $ dseq 2018-01-01 2018-12-30 < dseq.36.ref $ rm -f -- "dseq.36.ref" $ ## dseq.36.clit ends here dateutils-0.4.5/test/dseq.37.clit000066400000000000000000000003041335042257000165340ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 2016-01-01 2017-01-01 -f ywd > "dseq.37.ref" $ dseq 2015-W53-5 2016-W52-07 < dseq.37.ref $ rm -f -- "dseq.37.ref" $ ## dseq.37.clit ends here dateutils-0.4.5/test/dseq.38.clit000066400000000000000000000003141335042257000165360ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 2016-01-01 2017-01-01 | dconv -f ywd > "dseq.38.ref" $ dseq 2015-W53-5 2016-W52-07 < dseq.38.ref $ rm -f -- "dseq.38.ref" $ ## dseq.38.clit ends here dateutils-0.4.5/test/dseq.39.clit000066400000000000000000000003041335042257000165360ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 2015-W53-5 2016-W52-07 -f ymd > "dseq.39.ref" $ dseq 2016-01-01 2017-01-01 < dseq.39.ref $ rm -f -- "dseq.39.ref" $ ## dseq.39.clit ends here dateutils-0.4.5/test/dseq.40.clit000066400000000000000000000003141335042257000165270ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 2015-W53-5 2016-W52-07 | dconv -f ymd > "dseq.40.ref" $ dseq 2016-01-01 2017-01-01 < dseq.40.ref $ rm -f -- "dseq.40.ref" $ ## dseq.40.clit ends here dateutils-0.4.5/test/dseq.41.clit000066400000000000000000000002321335042257000165270ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq Jan Dec -i '%b' -f '%b' Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec $ ## dseq.41.clit ends here dateutils-0.4.5/test/dseq.42.clit000066400000000000000000000002371335042257000165350ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq Jan +1mo Dec -i '%b' -f '%b' Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec $ ## dseq.42.clit ends here dateutils-0.4.5/test/dseq.43.clit000066400000000000000000000006331335042257000165360ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- ## Frank O'Carroll's report $ dseq 2015-06-01 2015-06-07 --skip sun-sat $ dseq 2015-06-01 2015-06-07 --skip mon-sun $ dseq 2015-06-01 2015-06-07 --skip tue-mon $ dseq 2015-06-01 2015-06-07 --skip wed-tue $ dseq 2015-06-01 2015-06-07 --skip thu-wed $ dseq 2015-06-01 2015-06-07 --skip fri-thu $ dseq 2015-06-01 2015-06-07 --skip sat-fri $ ## dseq.43.clit ends here dateutils-0.4.5/test/dseq.44.clit000066400000000000000000000012671335042257000165430ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq -i %rY%V%u -f '%Y %m %d %G %V %u' 20160101 20160407 2016 01 04 2016 01 1 2016 01 05 2016 01 2 2016 01 06 2016 01 3 2016 01 07 2016 01 4 2016 01 08 2016 01 5 2016 01 09 2016 01 6 2016 01 10 2016 01 7 2016 01 11 2016 02 1 2016 01 12 2016 02 2 2016 01 13 2016 02 3 2016 01 14 2016 02 4 2016 01 15 2016 02 5 2016 01 16 2016 02 6 2016 01 17 2016 02 7 2016 01 18 2016 03 1 2016 01 19 2016 03 2 2016 01 20 2016 03 3 2016 01 21 2016 03 4 2016 01 22 2016 03 5 2016 01 23 2016 03 6 2016 01 24 2016 03 7 2016 01 25 2016 04 1 2016 01 26 2016 04 2 2016 01 27 2016 04 3 2016 01 28 2016 04 4 2016 01 29 2016 04 5 2016 01 30 2016 04 6 2016 01 31 2016 04 7 $ dateutils-0.4.5/test/dseq.45.clit000066400000000000000000000013651335042257000165430ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq -i %Y%m%d -f '%Y %m %d %G %V %u' 20160101 20160131 2016 01 01 2015 53 5 2016 01 02 2015 53 6 2016 01 03 2015 53 7 2016 01 04 2016 01 1 2016 01 05 2016 01 2 2016 01 06 2016 01 3 2016 01 07 2016 01 4 2016 01 08 2016 01 5 2016 01 09 2016 01 6 2016 01 10 2016 01 7 2016 01 11 2016 02 1 2016 01 12 2016 02 2 2016 01 13 2016 02 3 2016 01 14 2016 02 4 2016 01 15 2016 02 5 2016 01 16 2016 02 6 2016 01 17 2016 02 7 2016 01 18 2016 03 1 2016 01 19 2016 03 2 2016 01 20 2016 03 3 2016 01 21 2016 03 4 2016 01 22 2016 03 5 2016 01 23 2016 03 6 2016 01 24 2016 03 7 2016 01 25 2016 04 1 2016 01 26 2016 04 2 2016 01 27 2016 04 3 2016 01 28 2016 04 4 2016 01 29 2016 04 5 2016 01 30 2016 04 6 2016 01 31 2016 04 7 $ dateutils-0.4.5/test/dseq.46.clit000066400000000000000000000002501335042257000165340ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq Dzi +1mo N\'w --from-locale ts_ZA -i '%b' -f '%b' Apr May Jun Jul Aug Sep Oct Nov Dec $ ## dseq.46.clit ends here dateutils-0.4.5/test/dseq.47.clit000066400000000000000000000002421335042257000165360ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq Apr +1mo Dec --locale ts_ZA -i '%b' -f '%b' Dzi Mud Kho Maw Mha Ndz Nhl Huk N'w $ ## dseq.47.clit ends here dateutils-0.4.5/test/dseq.48.clit000066400000000000000000000002441335042257000165410ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 2010-01-31 +1mo 2010-05-31 2010-01-31 2010-02-28 2010-03-31 2010-04-30 2010-05-31 $ ## dseq.48.clit ends here dateutils-0.4.5/test/dseq.49.clit000066400000000000000000000003171335042257000165430ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 2008-02-29 +1y 2016-02-29 2008-02-29 2009-02-28 2010-02-28 2011-02-28 2012-02-29 2013-02-28 2014-02-28 2015-02-28 2016-02-29 $ ## dseq.49.clit ends here dateutils-0.4.5/test/dseq.50.clit000066400000000000000000000002711335042257000165320ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 2008-366 +1y 2016-366 2008-366 2009-365 2010-365 2011-365 2012-366 2013-365 2014-365 2015-365 2016-366 $ ## dseq.50.clit ends here dateutils-0.4.5/test/dseq.51.clit000066400000000000000000000002711335042257000165330ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 2009-W53-1 +1y 2015-W53-1 2009-W53-1 2010-W52-1 2011-W52-1 2012-W52-1 2013-W52-1 2014-W52-1 2015-W53-1 $ ## dseq.51.clit ends here dateutils-0.4.5/test/dseq.52.clit000066400000000000000000000002711335042257000165340ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 2016-01-05-00 +1mo 2016-05-05-00 2016-01-05-00 2016-02-04-00 2016-03-04-00 2016-04-04-00 2016-05-05-00 $ ## dseq.52.clit ends here dateutils-0.4.5/test/dseq.53.clit000066400000000000000000000002671335042257000165420ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 2016-03-23b +1mo 2016-08-23b 2016-03-23b 2016-04-21b 2016-05-22b 2016-06-22b 2016-07-21b 2016-08-23b $ ## dseq.53.clit ends here dateutils-0.4.5/test/dseq.54.clit000066400000000000000000000002731335042257000165400ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 2008-366 +1y 2016-12-31 2008-366 2009-365 2010-365 2011-365 2012-366 2013-365 2014-365 2015-365 2016-366 $ ## dseq.54.clit ends here dateutils-0.4.5/test/dseq.55.clit000066400000000000000000000003041335042257000165340ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 2009-W53-1 +1y 2016-12-31 2009-W53-1 2010-W52-1 2011-W52-1 2012-W52-1 2013-W52-1 2014-W52-1 2015-W53-1 2016-W52-1 $ ## dseq.55.clit ends here dateutils-0.4.5/test/dseq.56.clit000066400000000000000000000002661335042257000165440ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 2016-01-05-00 +1mo 2016-05-31 2016-01-05-00 2016-02-04-00 2016-03-04-00 2016-04-04-00 2016-05-05-00 $ ## dseq.56.clit ends here dateutils-0.4.5/test/dseq.57.clit000066400000000000000000000002301335042257000165340ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 2012-01-01 +2y 2018-01-01 2012-01-01 2014-01-01 2016-01-01 2018-01-01 $ ## dseq.57.clit ends here dateutils-0.4.5/test/dseq.58.clit000066400000000000000000000002301335042257000165350ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 2012-01-00 +2y 2018-01-00 2012-01-00 2014-01-00 2016-01-00 2018-01-00 $ ## dseq.58.clit ends here dateutils-0.4.5/test/dseq.59.clit000066400000000000000000000002301335042257000165360ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 2012-00-00 +2y 2018-00-00 2012-00-00 2014-00-00 2016-00-00 2018-00-00 $ ## dseq.59.clit ends here dateutils-0.4.5/test/dseq.60.clit000066400000000000000000000002721335042257000165340ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 2012-01-01 +2mo 2013-01-01 2012-01-01 2012-03-01 2012-05-01 2012-07-01 2012-09-01 2012-11-01 2013-01-01 $ ## dseq.60.clit ends here dateutils-0.4.5/test/dseq.61.clit000066400000000000000000000002721335042257000165350ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 2012-01-00 +2mo 2013-01-00 2012-01-00 2012-03-00 2012-05-00 2012-07-00 2012-09-00 2012-11-00 2013-01-00 $ ## dseq.61.clit ends here dateutils-0.4.5/test/dsort.001.clit000066400000000000000000000011161335042257000170040ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dsort < "${srcdir}/caev_01.txt" 2009-06-03 caev="DVCA" secu="VOD" exch="XLON" xdte="2009-06-03" nett/GBX="5.2" 2010-11-17 caev="DVCA" secu="VOD" exch="XLON" xdte="2010-11-17" nett/GBX="2.85" 2011-11-16 caev="DVCA" secu="VOD" exch="XLON" xdte="2011-11-16" nett/GBX="3.05" 2012-06-06 caev="DVCA" secu="VOD" exch="XLON" xdte="2012-06-06" nett/GBX="6.47" 2013-06-12 caev="DVCA" secu="VOD" exch="XLON" xdte="2013-06-12" nett/GBX="6.92" 2013-11-20 caev="DVCA" secu="VOD" exch="XLON" xdte="2013-11-20" nett/GBX="3.53" $ ## dsort.001.clit ends here dateutils-0.4.5/test/dsort.002.clit000066400000000000000000000011141335042257000170030ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dsort "${srcdir}/caev_01.txt" 2009-06-03 caev="DVCA" secu="VOD" exch="XLON" xdte="2009-06-03" nett/GBX="5.2" 2010-11-17 caev="DVCA" secu="VOD" exch="XLON" xdte="2010-11-17" nett/GBX="2.85" 2011-11-16 caev="DVCA" secu="VOD" exch="XLON" xdte="2011-11-16" nett/GBX="3.05" 2012-06-06 caev="DVCA" secu="VOD" exch="XLON" xdte="2012-06-06" nett/GBX="6.47" 2013-06-12 caev="DVCA" secu="VOD" exch="XLON" xdte="2013-06-12" nett/GBX="6.92" 2013-11-20 caev="DVCA" secu="VOD" exch="XLON" xdte="2013-11-20" nett/GBX="3.53" $ ## dsort.002.clit ends here dateutils-0.4.5/test/dsort.003.clit000066400000000000000000000011211335042257000170020ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dsort -r < "${srcdir}/caev_01.txt" 2013-11-20 caev="DVCA" secu="VOD" exch="XLON" xdte="2013-11-20" nett/GBX="3.53" 2013-06-12 caev="DVCA" secu="VOD" exch="XLON" xdte="2013-06-12" nett/GBX="6.92" 2012-06-06 caev="DVCA" secu="VOD" exch="XLON" xdte="2012-06-06" nett/GBX="6.47" 2011-11-16 caev="DVCA" secu="VOD" exch="XLON" xdte="2011-11-16" nett/GBX="3.05" 2010-11-17 caev="DVCA" secu="VOD" exch="XLON" xdte="2010-11-17" nett/GBX="2.85" 2009-06-03 caev="DVCA" secu="VOD" exch="XLON" xdte="2009-06-03" nett/GBX="5.2" $ ## dsort.003.clit ends here dateutils-0.4.5/test/dsort.004.clit000066400000000000000000000011171335042257000170100ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dsort -r "${srcdir}/caev_01.txt" 2013-11-20 caev="DVCA" secu="VOD" exch="XLON" xdte="2013-11-20" nett/GBX="3.53" 2013-06-12 caev="DVCA" secu="VOD" exch="XLON" xdte="2013-06-12" nett/GBX="6.92" 2012-06-06 caev="DVCA" secu="VOD" exch="XLON" xdte="2012-06-06" nett/GBX="6.47" 2011-11-16 caev="DVCA" secu="VOD" exch="XLON" xdte="2011-11-16" nett/GBX="3.05" 2010-11-17 caev="DVCA" secu="VOD" exch="XLON" xdte="2010-11-17" nett/GBX="2.85" 2009-06-03 caev="DVCA" secu="VOD" exch="XLON" xdte="2009-06-03" nett/GBX="5.2" $ ## dsort.004.clit ends here dateutils-0.4.5/test/dsort.005.clit000066400000000000000000000011011335042257000170020ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dsort -u < "${srcdir}/caev_02.txt" 2009-06-03 caev="DVCA" secu="VOD" exch="XLON" xdte="2009-06-03" nett/GBX="5.2" 2010-11-17 caev="XXXX" secu="VOD" exch="XLON" xdte="2010-11-17" 2011-11-16 caev="DVCA" secu="VOD" exch="XLON" xdte="2011-11-16" nett/GBX="3.05" 2012-06-06 caev="DVCA" secu="VOD" exch="XLON" xdte="2012-06-06" nett/GBX="6.47" 2013-06-12 caev="DVCA" secu="VOD" exch="XLON" xdte="2013-06-12" nett/GBX="6.92" 2013-11-20 caev="DVCA" secu="VOD" exch="XLON" xdte="2013-11-20" nett/GBX="3.53" $ ## dsort.005.clit ends here dateutils-0.4.5/test/dsort.006.clit000066400000000000000000000010771335042257000170170ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dsort -u "${srcdir}/caev_02.txt" 2009-06-03 caev="DVCA" secu="VOD" exch="XLON" xdte="2009-06-03" nett/GBX="5.2" 2010-11-17 caev="XXXX" secu="VOD" exch="XLON" xdte="2010-11-17" 2011-11-16 caev="DVCA" secu="VOD" exch="XLON" xdte="2011-11-16" nett/GBX="3.05" 2012-06-06 caev="DVCA" secu="VOD" exch="XLON" xdte="2012-06-06" nett/GBX="6.47" 2013-06-12 caev="DVCA" secu="VOD" exch="XLON" xdte="2013-06-12" nett/GBX="6.92" 2013-11-20 caev="DVCA" secu="VOD" exch="XLON" xdte="2013-11-20" nett/GBX="3.53" $ ## dsort.006.clit ends here dateutils-0.4.5/test/dsort.007.clit000066400000000000000000000004561335042257000170200ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dsort -i '%B %Y' --from-locale yo_NG < #include #include #include "dt-core.h" #define CHECK_RES(rc, pred, args...) \ if (pred) { \ fprintf(stderr, args); \ res = rc; \ } #define CHECK(pred, args...) \ CHECK_RES(1, pred, args) #define CHECK_EQ(slot, val, args...) \ CHECK(slot != val, args, slot, val) static int add_d_only(void) { static const char str[] = "2012-03-28"; struct dt_dt_s d; struct dt_dtdur_s dur; int res = 0; /* 2012-03-28 (using no format) */ fprintf(stderr, "testing %s +1d ...\n", str); d = dt_strpdt(str, NULL, NULL); /* prep the duration */ dur.d = dt_make_ddur(DT_DURD, 1); dur.t = dt_t_initialiser(); /* the actual addition */ d = dt_dtadd(d, dur); CHECK(d.d.typ != DT_YMD, " TYPE DIFFERS %u ... should be %u\n", (unsigned int)d.d.typ, (unsigned int)DT_YMD); CHECK(d.t.u, " TIME COMPONENT NOT NAUGHT %" PRIu64 "\n", (uint64_t)d.t.u); CHECK(d.xxx, " FORMER DURATION BIT SET\n"); CHECK(d.neg, " NEGATED BIT SET\n"); CHECK(d.t.dur, " TIME DURATION BIT SET\n"); CHECK(d.t.neg, " TIME NEGATED BIT SET\n"); CHECK_EQ((unsigned int)d.d.ymd.y, 2012U, " YEAR %u ... should be %u\n"); CHECK_EQ((unsigned int)d.d.ymd.m, 3U, " MONTH %u ... should be %u\n"); CHECK_EQ((unsigned int)d.d.ymd.d, 29U, " DAY %u ... should be %u\n"); /* make sure the padding leaves no garbage */ CHECK_RES(res, d.d.ymd.u & ~0x1fffff, " PADDING NOT NAUGHT %x\n", (unsigned int)(d.d.ymd.u & ~0x1fffff)); return res; } static int add_t_only(void) { static const char str[] = "12:34:56"; struct dt_dt_s d; struct dt_dtdur_s dur = {(dt_dtdurtyp_t)DT_DURUNK}; int res = 0; /* 2012-03-28 (using no format) */ fprintf(stderr, "testing %s +1h ...\n", str); d = dt_strpdt(str, NULL, NULL); /* prep the duration */ dur.durtyp = DT_DURS; dur.dv = 3600; /* the actual addition */ d = dt_dtadd(d, dur); CHECK(d.typ != DT_SANDWICH_UNK, " TYPE DIFFERS %u ... should be %u\n", (unsigned int)d.typ, (unsigned int)DT_SANDWICH_UNK); CHECK(d.t.typ != DT_HMS, " TYPE DIFFERS %u ... should be %u\n", (unsigned int)d.t.typ, (unsigned int)DT_HMS); CHECK(d.d.u, " DATE COMPONENT NOT NAUGHT %" PRIu64 "\n", (uint64_t)d.d.u); CHECK(d.xxx, " FORMER DURATION BIT SET\n"); CHECK(d.neg, " NEGATED BIT SET\n"); CHECK(d.t.dur, " TIME DURATION BIT SET\n"); CHECK(d.t.neg, " TIME NEGATED BIT SET\n"); CHECK_EQ((unsigned int)d.t.hms.h, 13U, " HOUR %u ... should be %u\n"); CHECK_EQ((unsigned int)d.t.hms.m, 34U, " MINUTE %u ... should be %u\n"); CHECK_EQ((unsigned int)d.t.hms.s, 56U, " SECOND %u ... should be %u\n"); /* make sure the padding leaves no garbage */ CHECK_RES(res, d.t.hms.u & ~0x1f3f3f3fffffff, " PADDING NOT NAUGHT %x\n", (unsigned int)(d.t.hms.u & ~0x1f3f3f3fffffff)); return res; } static int dt_add_d(void) { static const char str[] = "2012-03-28T12:34:56"; struct dt_dt_s d; struct dt_dtdur_s dur; int res = 0; fprintf(stderr, "testing %s +1d ...\n", str); d = dt_strpdt(str, NULL, NULL); /* prep the duration */ dur.d = dt_make_ddur(DT_DURD, 1); dur.t = dt_t_initialiser(); /* the actual addition */ d = dt_dtadd(d, dur); CHECK(d.d.typ != DT_YMD, " TYPE DIFFERS %u ... should be %u\n", (unsigned int)d.d.typ, (unsigned int)DT_YMD); CHECK(d.xxx, " FORMER DURATION BIT SET\n"); CHECK(d.neg, " NEGATED BIT SET\n"); CHECK(d.t.dur, " TIME DURATION BIT SET\n"); CHECK(d.t.neg, " TIME NEGATED BIT SET\n"); CHECK_EQ((unsigned int)d.d.ymd.y, 2012U, " YEAR %u ... should be %u\n"); CHECK_EQ((unsigned int)d.d.ymd.m, 3U, " MONTH %u ... should be %u\n"); CHECK_EQ((unsigned int)d.d.ymd.d, 29U, " DAY %u ... should be %u\n"); CHECK_EQ((unsigned int)d.t.hms.h, 12U, " HOUR %u ... should be %u\n"); CHECK_EQ((unsigned int)d.t.hms.m, 34U, " MINUTE %u ... should be %u\n"); CHECK_EQ((unsigned int)d.t.hms.s, 56U, " SECOND %u ... should be %u\n"); /* make sure the padding leaves no garbage */ CHECK_RES(res, d.d.ymd.u & ~0x1fffff, " PADDING NOT NAUGHT %x\n", (unsigned int)(d.d.ymd.u & ~0x1fffff)); CHECK_RES(res, d.t.hms.u & ~0x1f3f3f3fffffff, " TIME PADDING NOT NAUGHT %x\n", (unsigned int)(d.t.hms.u & ~0x1f3f3f3fffffff)); return res; } static int dt_add_t(void) { static const char str[] = "2012-03-28T23:12:01"; struct dt_dt_s d; struct dt_dtdur_s dur = {(dt_dtdurtyp_t)DT_DURUNK}; int res = 0; fprintf(stderr, "testing %s +1h ...\n", str); d = dt_strpdt(str, NULL, NULL); /* prep the duration */ dur.durtyp = DT_DURS; dur.dv = 3600; /* the actual addition */ d = dt_dtadd(d, dur); CHECK(d.d.typ != DT_YMD, " DATE TYPE DIFFERS %u ... should be %u\n", (unsigned int)d.d.typ, (unsigned int)DT_YMD); CHECK(d.t.typ != DT_HMS, " TIME TYPE DIFFERS %u ... should be %u\n", (unsigned int)d.t.typ, (unsigned int)DT_HMS); CHECK(d.xxx, " FORMER DURATION BIT SET\n"); CHECK(d.neg, " NEGATED BIT SET\n"); CHECK(d.t.dur, " TIME DURATION BIT SET\n"); CHECK(d.t.neg, " TIME NEGATED BIT SET\n"); CHECK_EQ((unsigned int)d.d.ymd.y, 2012U, " YEAR %u ... should be %u\n"); CHECK_EQ((unsigned int)d.d.ymd.m, 3U, " MONTH %u ... should be %u\n"); CHECK_EQ((unsigned int)d.d.ymd.d, 29U, " DAY %u ... should be %u\n"); CHECK_EQ((unsigned int)d.t.hms.h, 00U, " HOUR %u ... should be %u\n"); CHECK_EQ((unsigned int)d.t.hms.m, 12U, " MINUTE %u ... should be %u\n"); CHECK_EQ((unsigned int)d.t.hms.s, 01U, " SECOND %u ... should be %u\n"); /* make sure the padding leaves no garbage */ CHECK_RES(res, d.d.ymd.u & ~0x1fffff, " PADDING NOT NAUGHT %x\n", (unsigned int)(d.d.ymd.u & ~0x1fffff)); CHECK_RES(res, d.t.hms.u & ~0x1f3f3f3fffffff, " TIME PADDING NOT NAUGHT %x\n", (unsigned int)(d.t.hms.u & ~0x1f3f3f3fffffff)); return res; } static int dt_add_dt(void) { static const char str[] = "2012-03-28T23:55:55"; struct dt_dt_s d; struct dt_dtdur_s dur = {(dt_dtdurtyp_t)DT_DURUNK}; int res = 0; fprintf(stderr, "testing %s +1d1h ...\n", str); d = dt_strpdt(str, NULL, NULL); /* prep the duration */ dur.d = dt_make_ddur(DT_DURD, 1); /* addition 1 */ d = dt_dtadd(d, dur); /* duration 2 */ dur.durtyp = DT_DURH; dur.dv = 1; /* addition 2 */ d = dt_dtadd(d, dur); CHECK(d.d.typ != DT_YMD, " DATE TYPE DIFFERS %u ... should be %u\n", (unsigned int)d.d.typ, (unsigned int)DT_YMD); CHECK(d.t.typ != DT_HMS, " TIME TYPE DIFFERS %u ... should be %u\n", (unsigned int)d.t.typ, (unsigned int)DT_HMS); CHECK(d.xxx, " FORMER DURATION BIT SET\n"); CHECK(d.neg, " NEGATED BIT SET\n"); CHECK(d.t.dur, " TIME DURATION BIT SET\n"); CHECK(d.t.neg, " TIME NEGATED BIT SET\n"); CHECK_EQ((unsigned int)d.d.ymd.y, 2012U, " YEAR %u ... should be %u\n"); CHECK_EQ((unsigned int)d.d.ymd.m, 3U, " MONTH %u ... should be %u\n"); CHECK_EQ((unsigned int)d.d.ymd.d, 30U, " DAY %u ... should be %u\n"); CHECK_EQ((unsigned int)d.t.hms.h, 00U, " HOUR %u ... should be %u\n"); CHECK_EQ((unsigned int)d.t.hms.m, 55U, " MINUTE %u ... should be %u\n"); CHECK_EQ((unsigned int)d.t.hms.s, 55U, " SECOND %u ... should be %u\n"); /* make sure the padding leaves no garbage */ CHECK_RES(res, d.d.ymd.u & ~0x1fffff, " PADDING NOT NAUGHT %x\n", (unsigned int)(d.d.ymd.u & ~0x1fffff)); CHECK_RES(res, d.t.hms.u & ~0x1f3f3f3fffffff, " TIME PADDING NOT NAUGHT %x\n", (unsigned int)(d.t.hms.u & ~0x1f3f3f3fffffff)); return res; } int main(void) { int res = 0; /* we just assume the parser works */ if (add_d_only() != 0) { res = 1; } if (add_t_only() != 0) { res = 1; } if (dt_add_d() != 0) { res = 1; } if (dt_add_t() != 0) { res = 1; } if (dt_add_dt() != 0) { res = 1; } return res; } /* dtcore-add.c ends here */ dateutils-0.4.5/test/dtcore-conv.c000066400000000000000000000052621335042257000170720ustar00rootroot00000000000000#if defined HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include #include #include #include "dt-core.h" #define CHECK_RES(rc, pred, args...) \ if (pred) { \ fprintf(stderr, args); \ res = rc; \ } #define CHECK(pred, args...) \ CHECK_RES(1, pred, args) #define CHECK_EQ(slot, val, args...) \ CHECK(slot != val, args, slot, val) static int conv_chk(struct dt_dt_s tes, struct dt_dt_s ref) { int res = 0; CHECK(tes.typ != ref.typ, " TYPE DIFFERS %u ... should be %u\n", (unsigned int)tes.typ, (unsigned int)ref.typ); if (!ref.xxx) { CHECK(tes.xxx, " FORMER DURATION BIT SET\n"); } else { CHECK(!tes.xxx, " FORMER DURATION BIT NOT SET\n"); } if (!ref.neg) { CHECK(tes.neg, " NEGATED BIT SET\n"); } else { CHECK(!tes.neg, " NEGATED BIT NOT SET\n"); } if (tes.typ == DT_SEXY || tes.typ == DT_SEXYTAI) { /* make sure the padding leaves no garbage */ CHECK_RES(1, tes.sexy != ref.sexy, " VALUES DIFFER %u v %u\n", (unsigned int)tes.sexy, (unsigned int)ref.sexy); } return res; } int main(void) { int rc = 0; struct dt_dt_s t; struct dt_dt_s res; struct dt_dt_s chk; /* conv, then check */ t = dt_dt_initialiser(); t.sandwich = 1; t.d.typ = DT_YMD; t.d.ymd.y = 2012; t.d.ymd.m = 6; t.d.ymd.d = 30; t.t.typ = DT_HMS; t.t.hms.h = 23; t.t.hms.m = 59; t.t.hms.s = 59; chk = dt_dt_initialiser(); chk.typ = DT_SEXY; chk.sexy = 1341100799; if (res = dt_dtconv(DT_SEXY, t), conv_chk(res, chk)) { rc = 1; } /* conv, then check */ t = dt_dt_initialiser(); t.sandwich = 1; t.d.typ = DT_YMD; t.d.ymd.y = 2012; t.d.ymd.m = 7; t.d.ymd.d = 1; t.t.typ = DT_HMS; t.t.hms.h = 00; t.t.hms.m = 00; t.t.hms.s = 00; chk = dt_dt_initialiser(); chk.typ = DT_SEXY; chk.sexy = 1341100800; if (res = dt_dtconv(DT_SEXY, t), conv_chk(res, chk)) { rc = 1; } #if defined WITH_LEAP_SECONDS /* conv, then check */ t = dt_dt_initialiser(); t.sandwich = 1; t.d.typ = DT_YMD; t.d.ymd.y = 2012; t.d.ymd.m = 6; t.d.ymd.d = 30; t.t.typ = DT_HMS; t.t.hms.h = 23; t.t.hms.m = 59; t.t.hms.s = 59; chk = dt_dt_initialiser(); chk.typ = DT_SEXYTAI; chk.sexy = 1341100799 + 34; if (res = dt_dtconv(DT_SEXYTAI, t), conv_chk(res, chk)) { rc = 1; } /* conv, then check */ t = dt_dt_initialiser(); t.sandwich = 1; t.d.typ = DT_YMD; t.d.ymd.y = 2012; t.d.ymd.m = 7; t.d.ymd.d = 1; t.t.typ = DT_HMS; t.t.hms.h = 00; t.t.hms.m = 00; t.t.hms.s = 00; chk = dt_dt_initialiser(); chk.typ = DT_SEXYTAI; chk.sexy = 1341100800 + 35; if (res = dt_dtconv(DT_SEXYTAI, t), conv_chk(res, chk)) { rc = 1; } #endif /* WITH_LEAP_SECONDS */ return rc; } /* dtcore-conv.c ends here */ dateutils-0.4.5/test/dtcore-strp.c000066400000000000000000000116551335042257000171200ustar00rootroot00000000000000#if defined HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include #include #include #include "dt-core.h" #define CHECK_RES(rc, pred, args...) \ if (pred) { \ fprintf(stderr, args); \ res = rc; \ } #define CHECK(pred, args...) \ CHECK_RES(1, pred, args) static int test_d_only_no_fmt(void) { static const char str[] = "2012-03-28"; struct dt_dt_s d; int res = 0; /* 2012-03-28 (using no format) */ fprintf(stderr, "testing %s ...\n", str); d = dt_strpdt(str, NULL, NULL); CHECK(d.sandwich, " IS A SANDWICH ... but should be not\n"); CHECK(!dt_sandwich_only_d_p(d), " TYPE is not a d-only\n"); CHECK(d.d.typ != DT_YMD, " TYPE DIFFERS %u ... should be %u\n", (unsigned int)d.d.typ, (unsigned int)DT_YMD); CHECK(d.t.u, " TIME COMPONENT NOT NAUGHT %" PRIu64 "\n", (uint64_t)d.t.u); CHECK(d.xxx, " FORMER DURATION BIT SET\n"); CHECK(d.neg, " NEGATED BIT SET\n"); CHECK(d.t.dur, " TIME DURATION BIT SET\n"); CHECK(d.t.neg, " TIME NEGATED BIT SET\n"); CHECK(d.d.ymd.y != 2012, " YEAR %u ... should be 2012\n", (unsigned int)d.d.ymd.y); CHECK(d.d.ymd.m != 3, " MONTH %u ... should be 3\n", (unsigned int)d.d.ymd.m); CHECK(d.d.ymd.d != 28, " DAY %u ... should be 28\n", (unsigned int)d.d.ymd.d); /* make sure the padding leaves no garbage, not fatal tho */ CHECK_RES(res, d.d.ymd.u & ~0x1fffff, " PADDING NOT NAUGHT %x\n", (unsigned int)(d.d.ymd.u & ~0x1fffff)); return res; } static int test_t_only_no_fmt(void) { static const char str[] = "12:34:56"; struct dt_dt_s d; int res = 0; /* 12:34:56 (using no format) */ fprintf(stderr, "testing %s ...\n", str); d = dt_strpdt(str, NULL, NULL); CHECK(!d.sandwich, " NOT A SANDWICH ... but should be\n"); CHECK(!dt_sandwich_only_t_p(d), " TYPE is not a t-only\n"); CHECK(d.typ != DT_SANDWICH_UNK, " TYPE DIFFERS %u ... should be %u\n", (unsigned int)d.typ, (unsigned int)DT_SANDWICH_UNK); CHECK(d.t.typ != DT_HMS, " TIME TYPE DIFFERS %u ... should be %u\n", (unsigned int)d.t.typ, (unsigned int)DT_HMS); CHECK(d.d.u, " DATE COMPONENT NOT NAUGHT %" PRIu64 "\n", (uint64_t)d.d.u); CHECK(d.xxx, " FORMER DURATION BIT SET\n"); CHECK(d.neg, " NEGATED BIT SET\n"); CHECK(d.t.dur, " TIME DURATION BIT SET\n"); CHECK(d.t.neg, " TIME DURATION BIT SET\n"); CHECK(d.t.hms.h != 12, " HOUR %u ... should be 12\n", (unsigned int)d.t.hms.h); CHECK(d.t.hms.m != 34, " MINUTE %u ... should be 34\n", (unsigned int)d.t.hms.m); CHECK(d.t.hms.s != 56, " SECOND %u ... should be 56\n", (unsigned int)d.t.hms.s); CHECK(d.t.hms.ns != 0, " NANOSECOND %u ... should be 0\n", (unsigned int)d.t.hms.ns); /* make sure the padding leaves no garbage */ CHECK_RES(res, d.t.hms.u & ~0x1f3f3f3fffffff, " PADDING NOT NAUGHT %x\n", (unsigned int)(d.t.hms.u & ~0x1f3f3f3fffffff)); return res; } static int test_dt_no_fmt(void) { static const char str[] = "2012-03-28 12:34:56"; struct dt_dt_s d; int res = 0; fprintf(stderr, "testing %s ...\n", str); d = dt_strpdt(str, NULL, NULL); CHECK(!d.sandwich, " NOT A SANDWICH ... but should be\n"); CHECK(!dt_sandwich_p(d), " TYPE is not a sandwich\n"); CHECK(d.d.typ != DT_YMD, " TYPE DIFFERS %u ... should be %u\n", (unsigned int)d.d.typ, (unsigned int)DT_YMD); CHECK(d.t.typ != DT_HMS, " TIME TYPE DIFFERS %u ... should be %u\n", (unsigned int)d.t.typ, (unsigned int)DT_HMS); CHECK(d.xxx, " FORMER DURATION BIT SET\n"); CHECK(d.neg, " NEGATED BIT SET\n"); CHECK(d.t.dur, " TIME DURATION BIT SET\n"); CHECK(d.t.neg, " TIME DURATION BIT SET\n"); CHECK(d.d.ymd.y != 2012, " YEAR %u ... should be 2012\n", (unsigned int)d.d.ymd.y); CHECK(d.d.ymd.m != 3, " MONTH %u ... should be 3\n", (unsigned int)d.d.ymd.m); CHECK(d.d.ymd.d != 28, " DAY %u ... should be 28\n", (unsigned int)d.d.ymd.d); CHECK(d.t.hms.h != 12, " HOUR %u ... should be 12\n", (unsigned int)d.t.hms.h); CHECK(d.t.hms.m != 34, " MINUTE %u ... should be 34\n", (unsigned int)d.t.hms.m); CHECK(d.t.hms.s != 56, " SECOND %u ... should be 56\n", (unsigned int)d.t.hms.s); CHECK(d.t.hms.ns != 0, " NANOSECOND %u ... should be 0\n", (unsigned int)d.t.hms.ns); /* make sure the padding leaves no garbage */ CHECK_RES(res, d.d.ymd.u & ~0x1fffff, " PADDING NOT NAUGHT %x\n", (unsigned int)(d.d.ymd.u & ~0x1fffff)); CHECK_RES(res, d.t.hms.u & ~0x1f3f3f3fffffff, " PADDING NOT NAUGHT %x\n", (unsigned int)(d.t.hms.u & ~0x1f3f3f3fffffff)); return res; } int main(void) { int res = 0; if (test_d_only_no_fmt() != 0) { res = 1; } if (test_t_only_no_fmt() != 0) { res = 1; } if (test_dt_no_fmt() != 0) { res = 1; } return res; } /* dtcore-strpd.c ends here */ dateutils-0.4.5/test/dtdiff.001.clit000066400000000000000000000002011335042257000171030ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ ddiff 2012-03-02T10:04:00 2012-03-02T10:14:00 600s $ ## dtdiff.1.clit ends here dateutils-0.4.5/test/dtdiff.002.clit000066400000000000000000000002101335042257000171040ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ ddiff 2012-03-02T10:04:00 2012-03-02T10:14:00 -f '%S' 600 $ ## dtdiff.2.clit ends here dateutils-0.4.5/test/dtdiff.003.clit000066400000000000000000000002171335042257000171140ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ ddiff 2012-03-02T10:04:00 2012-03-02T10:14:00 -f '%M min' 10 min $ ## dtdiff.3.clit ends here dateutils-0.4.5/test/dtdiff.004.clit000066400000000000000000000002021335042257000171070ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ ddiff 2012-03-02T10:14:00 2012-03-02T10:04:00 -600s $ ## dtdiff.4.clit ends here dateutils-0.4.5/test/dtdiff.005.clit000066400000000000000000000001651335042257000171200ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ ddiff 2012-03-02T10:14:00 2012-03-03 1 $ ## dtdiff.5.clit ends here dateutils-0.4.5/test/dtdiff.006.clit000066400000000000000000000001761335042257000171230ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ ddiff 2012-03-02 2012-03-03T10:14:00 -f '%F' 1d $ ## dtdiff.6.clit ends here dateutils-0.4.5/test/dtdiff.007.clit000066400000000000000000000001661335042257000171230ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ ddiff 2012-03-03T10:14:00 2012-03-02 -1 $ ## dtdiff.7.clit ends here dateutils-0.4.5/test/dtdiff.008.clit000066400000000000000000000001771335042257000171260ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ ddiff 2012-03-03 2012-03-02T10:14:00 -f '%F' -1d $ ## dtdiff.8.clit ends here dateutils-0.4.5/test/dtdiff.009.clit000066400000000000000000000001641335042257000171230ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ ?2 ddiff 12:14:00 2012-03-02T10:14:00 $ ## dtdiff.9.clit ends here dateutils-0.4.5/test/dtdiff.010.clit000066400000000000000000000001541335042257000171120ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ ?2 ddiff 2012-03-02 10:14:00 $ ## dtdiff.10.clit ends here dateutils-0.4.5/test/dtdiff.011.clit000066400000000000000000000002041335042257000171070ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ ddiff 2012-03-01T12:17:00 2012-03-02T14:00:00 92580s $ ## dtdiff.11.clit ends here dateutils-0.4.5/test/dtdiff.012.clit000066400000000000000000000002611335042257000171130ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ ddiff 2012-03-01T12:17:00 2012-03-02T14:00:00 -f '%d days and %S seconds' 1 days and 6180 seconds $ ## dtdiff.12.clit ends here dateutils-0.4.5/test/dtdiff.013.clit000066400000000000000000000002351335042257000171150ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ ddiff 2012-03-25T01:45:00 2012-03-25T03:15:00 --from-zone Europe/Berlin 1800s $ ## dtdiff.13.clit ends here dateutils-0.4.5/test/dtdiff.014.clit000066400000000000000000000002351335042257000171160ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ ddiff 2012-03-25T01:45:00 2012-03-25T02:15:00 --from-zone Europe/Berlin 1800s $ ## dtdiff.14.clit ends here dateutils-0.4.5/test/dtdiff.015.clit000066400000000000000000000002351335042257000171170ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ ddiff 2012-10-28T01:45:00 2012-10-28T02:15:00 --from-zone Europe/Berlin 5400s $ ## dtdiff.15.clit ends here dateutils-0.4.5/test/dtdiff.016.clit000066400000000000000000000002351335042257000171200ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ ddiff 2012-10-28T01:45:00 2012-10-28T03:15:00 --from-zone Europe/Berlin 9000s $ ## dtdiff.16.clit ends here dateutils-0.4.5/test/dtdiff.017.clit000066400000000000000000000002051335042257000171160ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ ddiff '2012-06-30 23:59:00' '2012-07-01 00:00:00' 60s $ ## dtdiff.17.clit ends here dateutils-0.4.5/test/dtdiff.018.clit000066400000000000000000000002051335042257000171170ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ ddiff '2012-06-30 23:59:00' '2012-06-30 23:59:60' 60s $ ## dtdiff.18.clit ends here dateutils-0.4.5/test/dtdiff.019.clit000066400000000000000000000002171335042257000171230ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ ddiff '2012-06-30 23:59:00' '2012-07-01 00:00:00' -f '%rSs' 61s $ ## dtdiff.19.clit ends here dateutils-0.4.5/test/dtdiff.020.clit000066400000000000000000000002171335042257000171130ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ ddiff '2012-06-30 23:59:00' '2012-06-30 23:59:60' -f '%rSs' 60s $ ## dtdiff.20.clit ends here dateutils-0.4.5/test/dtdiff.021.clit000066400000000000000000000002161335042257000171130ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ ddiff '2012-06-30 23:59:00' '2012-07-01 00:00:00' -f '%rT' 61s $ ## dtdiff.21.clit ends here dateutils-0.4.5/test/dtdiff.022.clit000066400000000000000000000002161335042257000171140ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ ddiff '2012-06-30 23:59:00' '2012-06-30 23:59:60' -f '%rT' 60s $ ## dtdiff.22.clit ends here dateutils-0.4.5/test/dtdiff.023.clit000066400000000000000000000002151335042257000171140ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ ddiff '2012-05-01 14:00:00' '2012-05-10 15:00:00' -f '%db' 7b $ ## dtdiff.23.clit ends here dateutils-0.4.5/test/dtdiff.024.clit000066400000000000000000000002161335042257000171160ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ ddiff '2012-05-30 14:00:00' '2012-05-18 17:00:00' -f '%db' -7b $ ## dtdiff.24.clit ends here dateutils-0.4.5/test/dtdiff.025.clit000066400000000000000000000002311335042257000171140ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ ddiff '2012-05-30 14:00:00' '2012-05-18 17:00:00' -f 'bizsi' -7bT21:00:00 $ ## dtdiff.25.clit ends here dateutils-0.4.5/test/dtdiff.026.clit000066400000000000000000000002301335042257000171140ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ ddiff '2012-05-01 14:00:00' '2012-05-10 15:00:00' -f 'bizsi' 7bT01:00:00 $ ## dtdiff.26.clit ends here dateutils-0.4.5/test/dtdiff.027.clit000066400000000000000000000002401335042257000171160ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ ddiff --from-zone Australia/Sydney 2013-04-15T08:30:00 2013-04-15T09:00:00 1800s $ ## dtdiff.27.clit ends here dateutils-0.4.5/test/dtdiff.028.clit000066400000000000000000000002521335042257000171220ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ ddiff --from-zone Australia/Sydney 2013-04-15T08:30:00 <16:00:00 <=11:00:00' < 2012-03-25T03:00:00+02:00 Europe/Berlin $ ## dzone.005.clit ends here dateutils-0.4.5/test/dzone.006.clit000066400000000000000000000002721335042257000167770ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dzone --prev Europe/Berlin 2014-02-22 2013-10-27T03:00:00+02:00 <- 2013-10-27T02:00:00+01:00 Europe/Berlin $ ## dzone.006.clit ends here dateutils-0.4.5/test/dzone.007.clit000066400000000000000000000002771335042257000170050ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- ## Singapore stopped transitioning in 1982 $ dzone --next Asia/Singapore 2014-02-22 never -> never Asia/Singapore $ ## dzone.007.clit ends here dateutils-0.4.5/test/dzone.008.clit000066400000000000000000000002741335042257000170030ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dzone --prev Asia/Singapore 2014-02-22 1982-01-01T00:00:00+07:30 <- 1982-01-01T00:30:00+08:00 Asia/Singapore $ ## dzone.008.clit ends here dateutils-0.4.5/test/dzone.009.clit000066400000000000000000000001631335042257000170010ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dzone --prev UTC never <- never UTC $ ## dzone.009.clit ends here dateutils-0.4.5/test/dzone.010.clit000066400000000000000000000001631335042257000167710ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dzone --next UTC never -> never UTC $ ## dzone.010.clit ends here dateutils-0.4.5/test/dzone.011.clit000066400000000000000000000003561335042257000167760ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dzone --next Europe/Berlin -i '%Y-%b-%dT%T' --from-locale fi_FI '2012-maalis-04T12:04:11' 2012-03-25T02:00:00+01:00 -> 2012-03-25T03:00:00+02:00 Europe/Berlin $ ## dzone.011.clit ends here dateutils-0.4.5/test/dzone.012.clit000066400000000000000000000003151335042257000167720ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dzone UTC Europe/Moscow America/Bogota 08:00:00 08:00:00+00:00 UTC 11:00:00+03:00 Europe/Moscow 03:00:00-05:00 America/Bogota $ ## dzone.012.clit ends here dateutils-0.4.5/test/dzone.013.clit000066400000000000000000000003731335042257000167770ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dzone Europe/Berlin Australia/Sydney America/Buenos_Aires 2018-05-31 2018-05-31+02:00 Europe/Berlin 2018-05-31+10:00 Australia/Sydney 2018-05-31-03:00 America/Buenos_Aires $ ## dzone.013.clit ends here dateutils-0.4.5/test/dzone.014.clit000066400000000000000000000010041335042257000167700ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- ## this is issue #80 $ dzone --input-format='%m/%d/%Y,%H:%M' --from-zone='America/New_York' UTC '03/14/2017,11:30' 2017-03-14T15:30:00+00:00 UTC $ dzone --input-format='%m/%d/%Y,%H:%M' --from-zone='America/New_York' '03/14/2017,11:30' 2017-03-14T15:30:00-04:00 $ dzone --input-format='%m/%d/%Y,%H:%M' UTC '03/14/2017,11:30' 2017-03-14T11:30:00+00:00 UTC $ dzone --input-format='%m/%d/%Y,%H:%M' '03/14/2017,11:30' 2017-03-14T11:30:00+00:00 $ ## dzone.014.clit ends here dateutils-0.4.5/test/enum-1.c000066400000000000000000000010411335042257000157400ustar00rootroot00000000000000#if defined HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include #include "dt-core.h" int main(void) { int res = 0; if ((unsigned int)DT_PACK != (unsigned int)DT_NDTYP) { fprintf(stderr, "DT_PACK %u != DT_NDTYP %u\n", (unsigned int)DT_PACK, (unsigned int)DT_NDTYP); res = 1; } if ((unsigned int)DT_SEXY != (unsigned int)(DT_NDTYP + 1U)) { fprintf(stderr, "DT_SEXY %u != DT_NTYP + 1 %u\n", (unsigned int)DT_SEXY, (unsigned int)(DT_NDTYP + 1U)); res = 1; } return res; } /* enum-1.c ends here */ dateutils-0.4.5/test/itostr-1.c000066400000000000000000000025351335042257000163310ustar00rootroot00000000000000#include #include "strops.h" #include "nifty.h" int main(void) { static char buf[32U]; buf[ui99topstr(buf, 32U, 23U, 2U, ' ')] = '\0'; puts(buf); buf[ui99topstr(buf, 32U, 1U, 2U, ' ')] = '\0'; puts(buf); buf[ui99topstr(buf, 32U, 0U, 2U, ' ')] = '\0'; puts(buf); buf[ui99topstr(buf, 32U, 1U, 2U, '0')] = '\0'; puts(buf); buf[ui99topstr(buf, 32U, 23U, 2U, '0')] = '\0'; puts(buf); buf[ui99topstr(buf, 32U, 23U, 1U, ' ')] = '\0'; puts(buf); buf[ui99topstr(buf, 32U, 3U, 1U, ' ')] = '\0'; puts(buf); puts(""); buf[ui99topstr(buf, 32U, 23U, 2U, 0)] = '\0'; puts(buf); buf[ui99topstr(buf, 32U, 1U, 2U, 0)] = '\0'; puts(buf); buf[ui99topstr(buf, 32U, 0U, 2U, 0)] = '\0'; puts(buf); buf[ui99topstr(buf, 32U, 1U, 2U, 0)] = '\0'; puts(buf); buf[ui99topstr(buf, 32U, 23U, 2U, 0)] = '\0'; puts(buf); buf[ui99topstr(buf, 32U, 23U, 1U, 0)] = '\0'; puts(buf); buf[ui99topstr(buf, 32U, 3U, 1U, 0)] = '\0'; puts(buf); puts(""); buf[ui99topstr(buf, 1U, 23U, 2U, 0)] = '\0'; puts(buf); buf[ui99topstr(buf, 1U, 1U, 2U, 0)] = '\0'; puts(buf); buf[ui99topstr(buf, 1U, 0U, 2U, 0)] = '\0'; puts(buf); buf[ui99topstr(buf, 1U, 1U, 2U, 0)] = '\0'; puts(buf); buf[ui99topstr(buf, 1U, 23U, 2U, 0)] = '\0'; puts(buf); buf[ui99topstr(buf, 1U, 23U, 1U, 0)] = '\0'; puts(buf); buf[ui99topstr(buf, 1U, 3U, 1U, 0)] = '\0'; puts(buf); return 0; } dateutils-0.4.5/test/itostr-2.c000066400000000000000000000030741335042257000163310ustar00rootroot00000000000000#include #include "strops.h" #include "nifty.h" int main(void) { static char buf[32U]; buf[ui999topstr(buf, 32U, 123U, 3U, 0)] = '\0'; puts(buf); buf[ui999topstr(buf, 32U, 23U, 3U, ' ')] = '\0'; puts(buf); buf[ui999topstr(buf, 32U, 10U, 3U, ' ')] = '\0'; puts(buf); buf[ui999topstr(buf, 32U, 0U, 3U, ' ')] = '\0'; puts(buf); buf[ui999topstr(buf, 32U, 1U, 3U, '0')] = '\0'; puts(buf); buf[ui999topstr(buf, 32U, 123U, 3U, '0')] = '\0'; puts(buf); buf[ui999topstr(buf, 32U, 23U, 1U, ' ')] = '\0'; puts(buf); buf[ui999topstr(buf, 32U, 3U, 1U, ' ')] = '\0'; puts(buf); puts(""); buf[ui999topstr(buf, 32U, 123U, 2U, 0)] = '\0'; puts(buf); buf[ui999topstr(buf, 32U, 23U, 2U, ' ')] = '\0'; puts(buf); buf[ui999topstr(buf, 32U, 10U, 2U, ' ')] = '\0'; puts(buf); buf[ui999topstr(buf, 32U, 0U, 2U, ' ')] = '\0'; puts(buf); buf[ui999topstr(buf, 32U, 1U, 2U, '0')] = '\0'; puts(buf); buf[ui999topstr(buf, 32U, 123U, 2U, '0')] = '\0'; puts(buf); buf[ui999topstr(buf, 32U, 23U, 1U, ' ')] = '\0'; puts(buf); buf[ui999topstr(buf, 32U, 3U, 1U, ' ')] = '\0'; puts(buf); puts(""); buf[ui999topstr(buf, 2U, 123U, 2U, 0)] = '\0'; puts(buf); buf[ui999topstr(buf, 1U, 23U, 2U, 0)] = '\0'; puts(buf); buf[ui999topstr(buf, 1U, 10U, 2U, 0)] = '\0'; puts(buf); buf[ui999topstr(buf, 1U, 0U, 2U, 0)] = '\0'; puts(buf); buf[ui999topstr(buf, 1U, 1U, 2U, 0)] = '\0'; puts(buf); buf[ui999topstr(buf, 1U, 123U, 1U, 0)] = '\0'; puts(buf); buf[ui999topstr(buf, 2U, 23U, 1U, 0)] = '\0'; puts(buf); buf[ui999topstr(buf, 1U, 3U, 1U, 0)] = '\0'; puts(buf); return 0; } dateutils-0.4.5/test/itostr-3.c000066400000000000000000000031311335042257000163240ustar00rootroot00000000000000#include #include "strops.h" #include "nifty.h" int main(void) { static char buf[32U]; buf[ui9999topstr(buf, 32U, 1234U, 4U, 0)] = '\0'; puts(buf); buf[ui9999topstr(buf, 32U, 23U, 4U, ' ')] = '\0'; puts(buf); buf[ui9999topstr(buf, 32U, 10U, 3U, ' ')] = '\0'; puts(buf); buf[ui9999topstr(buf, 32U, 0U, 3U, '0')] = '\0'; puts(buf); buf[ui9999topstr(buf, 32U, 1U, 4U, '0')] = '\0'; puts(buf); buf[ui9999topstr(buf, 32U, 123U, 3U, '0')] = '\0'; puts(buf); buf[ui9999topstr(buf, 32U, 23U, 1U, ' ')] = '\0'; puts(buf); buf[ui9999topstr(buf, 32U, 3U, 4U, ' ')] = '\0'; puts(buf); puts(""); buf[ui9999topstr(buf, 32U, 1234U, 3U, 0)] = '\0'; puts(buf); buf[ui9999topstr(buf, 32U, 23U, 2U, ' ')] = '\0'; puts(buf); buf[ui9999topstr(buf, 32U, 10U, 2U, ' ')] = '\0'; puts(buf); buf[ui9999topstr(buf, 32U, 0U, 2U, ' ')] = '\0'; puts(buf); buf[ui9999topstr(buf, 32U, 1U, 2U, '0')] = '\0'; puts(buf); buf[ui9999topstr(buf, 32U, 123U, 2U, '0')] = '\0'; puts(buf); buf[ui9999topstr(buf, 32U, 23U, 4U, '0')] = '\0'; puts(buf); buf[ui9999topstr(buf, 32U, 3U, 1U, ' ')] = '\0'; puts(buf); puts(""); buf[ui9999topstr(buf, 3U, 1234U, 2U, 0)] = '\0'; puts(buf); buf[ui9999topstr(buf, 1U, 23U, 4U, 0)] = '\0'; puts(buf); buf[ui9999topstr(buf, 2U, 23U, 4U, 0)] = '\0'; puts(buf); buf[ui9999topstr(buf, 3U, 23U, 4U, 0)] = '\0'; puts(buf); buf[ui9999topstr(buf, 4U, 23U, 4U, 0)] = '\0'; puts(buf); buf[ui9999topstr(buf, 1U, 123U, 1U, 0)] = '\0'; puts(buf); buf[ui9999topstr(buf, 1U, 23U, 1U, 0)] = '\0'; puts(buf); buf[ui9999topstr(buf, 1U, 3U, 1U, 0)] = '\0'; puts(buf); return 0; } dateutils-0.4.5/test/itostr-4.c000066400000000000000000000020231335042257000163240ustar00rootroot00000000000000#include #include "strops.h" #include "nifty.h" int main(void) { static char buf[32U]; buf[ui999999999tostr(buf, 32U, 0U)] = '\0'; puts(buf); buf[ui999999999tostr(buf, 32U, 1U)] = '\0'; puts(buf); buf[ui999999999tostr(buf, 32U, 1234U)] = '\0'; puts(buf); buf[ui999999999tostr(buf, 32U, 12345678U)] = '\0'; puts(buf); buf[ui999999999tostr(buf, 32U, 123456789U)] = '\0'; puts(buf); puts(""); buf[ui999999999tostr(buf, 6U, 0U)] = '\0'; puts(buf); buf[ui999999999tostr(buf, 6U, 1000U)] = '\0'; puts(buf); buf[ui999999999tostr(buf, 6U, 123400U)] = '\0'; puts(buf); buf[ui999999999tostr(buf, 6U, 12345678U)] = '\0'; puts(buf); buf[ui999999999tostr(buf, 6U, 123456789U)] = '\0'; puts(buf); puts(""); buf[ui999999999tostr(buf, 3U, 0U)] = '\0'; puts(buf); buf[ui999999999tostr(buf, 3U, 1U)] = '\0'; puts(buf); buf[ui999999999tostr(buf, 3U, 1234U)] = '\0'; puts(buf); buf[ui999999999tostr(buf, 3U, 12345678U)] = '\0'; puts(buf); buf[ui999999999tostr(buf, 3U, 123456789U)] = '\0'; puts(buf); return 0; } dateutils-0.4.5/test/itostr.001.clit000066400000000000000000000002161335042257000171750ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ itostr-1 23 1 0 01 23 23 3 23 1 0 1 23 23 3 3 1 0 1 3 3 3 $ ## itostr.001.clit ends here dateutils-0.4.5/test/itostr.002.clit000066400000000000000000000002431335042257000171760ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ itostr-2 123 23 10 0 001 123 23 3 123 23 10 0 01 123 23 3 23 3 0 0 1 3 23 3 $ ## itostr.002.clit ends here dateutils-0.4.5/test/itostr.003.clit000066400000000000000000000002571335042257000172040ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ itostr-3 1234 23 10 000 0001 123 23 3 1234 23 10 0 01 123 0023 3 234 3 23 23 23 3 3 3 $ ## itostr.003.clit ends here dateutils-0.4.5/test/itostr.004.clit000066400000000000000000000003041335042257000171760ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ itostr-4 000000000 000000001 000001234 012345678 123456789 000000 000001 000123 012345 123456 000 000 000 012 123 $ ## itostr.004.clit ends here dateutils-0.4.5/test/mil-midnight.001.clit000066400000000000000000000004551335042257000202400ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dconv 2014-10-01T24:00:00 2014-10-01T24:00:00 $ dconv 2014-10-01T24:00:01 2014-10-01 $ dconv 2014-10-01T24:00:00 -f ymcw 2014-10-01-03T24:00:00 $ dconv 2014-10-01T24:00:00 -f ywd 2014-W40-3T24:00:00 $ dconv 2014-10-01T24:00:00 -f lilian 157772.000000 $ dateutils-0.4.5/test/mil-midnight.002.clit000066400000000000000000000002151335042257000202330ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dadd 2014-10-01T24:00:00 +1d 2014-10-02T24:00:00 $ dadd 2014-10-01T24:00:01 +1d 2014-10-02 $ dateutils-0.4.5/test/mil-midnight.003.clit000066400000000000000000000002151335042257000202340ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dadd 2014-10-01T24:00:00 +1h 2014-10-02T01:00:00 $ dadd 2014-10-01T24:00:01 +1h 2014-10-01 $ dateutils-0.4.5/test/mil-midnight.004.clit000066400000000000000000000002311335042257000202330ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ ddiff 2014-10-01T23:00:00 2014-10-01T24:00:00 3600s $ ddiff 2014-10-01T24:00:00 2014-10-02T00:00:00 0s $ dateutils-0.4.5/test/mil-midnight.005.clit000066400000000000000000000003221335042257000202350ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dgrep '<=2014-10-01T24:00:00' <2014-01-01' 2014-08-08 $ printf "2014-08-08" | dgrep '>2014-01-01' 2014-08-08 $ dateutils-0.4.5/test/prchunk.006.clit000066400000000000000000000002151335042257000173270ustar00rootroot00000000000000#!/usr/bin/clitoris $ printf "2014-08-08\n" | strptime -i '%Y-%m-%d' 2014-08-08 $ printf "2014-08-08" | strptime -i '%Y-%m-%d' 2014-08-08 $ dateutils-0.4.5/test/some-dates-and-other-stuff.csv000066400000000000000000000001421335042257000222550ustar00rootroot000000000000002014-01-04T12:07:00+0400 2014-02-03T11:00:00+0200 2014-03-04 2014-04-?? 2014-05-10T10:00:00+0000 dateutils-0.4.5/test/strptime.001.clit000066400000000000000000000002111335042257000175130ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ strptime -i '%a, %b-%d/%Y' 'Mon, May-01/2000' 2000-05-01 $ ## strptime.1.clit ends here dateutils-0.4.5/test/strptime.002.clit000066400000000000000000000002541335042257000175230ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ strptime -i '%a, %b-%d/%Y' < #include "strops.h" #include "strops.c" #include "nifty.h" static const char *tst1[] = {"84", "52", "01", "99", "102", "120", "001", "4"}; static const char *tst0[] = {"8.4", "5a", "a1", "9.", "1+2", "", "\t", "#4"}; int main(void) { for (size_t i = 0U; i < countof(tst1); i++) { const char *x; int32_t r = strtoi_lim(tst1[i], &x, 0, 60); printf("%d %td\n", r, x - tst1[i]); } for (size_t i = 0U; i < countof(tst0); i++) { const char *x; int32_t r = strtoi_lim(tst0[i], &x, 0, 60); printf("%d %td\n", r, x - tst0[i]); } return 0; } dateutils-0.4.5/test/strtoi-bench.c000066400000000000000000000006411335042257000172440ustar00rootroot00000000000000#include #include "strops.h" #include "strops.c" #include "nifty.h" static const char *tst1[] = {"84", "52", "01", "99", "102", "120", "001", "4"}; static const char *tst0[] = {"8.4", "5a", "a1", "9.", "1+2", "", "\t", "#4"}; int main(void) { int32_t s = 0; for (size_t i = 0; i < 100000000U; i++) { const char *UNUSED(x); s += strtoi_lim(tst1[0U], &x, 0, 90); } printf("%d\n", s); return 0; } dateutils-0.4.5/test/strtoi.001.clit000066400000000000000000000002421335042257000171740ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ strtoi-1 -2 2 52 2 1 2 -2 2 10 2 12 2 0 2 4 1 8 1 5 1 -1 0 9 1 1 1 -1 0 -1 0 -1 0 $ ## strtoi.001.clit ends here dateutils-0.4.5/test/struct-1.c000066400000000000000000000003701335042257000163240ustar00rootroot00000000000000#if defined HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include "dt-core.h" int main(void) { struct dt_dt_s dt; dt.typ = (dt_dttyp_t)DT_UNK; if (dt.d.typ != DT_DUNK) { return 1; } return 0; } /* struct-1.c ends here */ dateutils-0.4.5/test/struct-2.c000066400000000000000000000003671335042257000163330ustar00rootroot00000000000000#if defined HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include "dt-core.h" int main(void) { struct dt_dt_s dt; dt.d.typ = DT_YMD; if (dt.typ != (dt_dttyp_t)DT_YMD) { return 1; } return 0; } /* struct-2.c ends here */ dateutils-0.4.5/test/struct-3.c000066400000000000000000000004241335042257000163260ustar00rootroot00000000000000#if defined HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include "dt-core.h" int main(void) { struct dt_dt_s dt; dt.xxx = 1; if (dt.d.xxx != 1) { return 1; } dt.xxx = 0; if (dt.d.xxx != 0) { return 1; } return 0; } /* struct-3.c ends here */ dateutils-0.4.5/test/struct-4.c000066400000000000000000000004241335042257000163270ustar00rootroot00000000000000#if defined HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include "dt-core.h" int main(void) { struct dt_dt_s dt; dt.neg = 1; if (dt.d.neg != 1) { return 1; } dt.neg = 0; if (dt.d.neg != 0) { return 1; } return 0; } /* struct-4.c ends here */ dateutils-0.4.5/test/struct-5.c000066400000000000000000000006211335042257000163270ustar00rootroot00000000000000#if defined HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include "dt-core.h" int main(void) { struct dt_dt_s dt; dt.neg = 0; dt.xxx = 0; dt.typ = DT_SEXY; if (dt.d.typ != (dt_dtyp_t)DT_SEXY || dt.d.neg || dt.d.xxx) { return 1; } dt_make_sandwich(&dt, DT_DUNK, DT_TUNK); if (!dt.sandwich || dt.d.neg || dt.d.xxx) { return 1; } return 0; } /* struct-5.c ends here */ dateutils-0.4.5/test/struct-6.c000066400000000000000000000005161335042257000163330ustar00rootroot00000000000000#if defined HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include #include #include "dt-core.h" int main(void) { struct dt_dt_s dt; memset(&dt, 0, sizeof(dt)); dt.sexy = 0x1fffffffffffffLL; if (dt.typ != DT_UNK || dt.xxx || dt.neg) { return 1; } return 0; } /* struct-6.c ends here */ dateutils-0.4.5/test/struct-7.c000066400000000000000000000013521335042257000163330ustar00rootroot00000000000000#if defined HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include #include "dt-core.h" int main(void) { int res = 0; #if !defined __uint128_t_defined typedef struct { uint64_t l; uint64_t h; } uint128_t; #define __uint128_t_defined #endif /* !uint128_t */ #define CHECK_SIZE(x, y) \ if (sizeof(x) != sizeof(y)) { \ fprintf( \ stderr, \ "sizeof(" #x ") -> %zu\t" \ "sizeof(" #y ") -> %zu\n", \ sizeof(x), sizeof(y)); \ res = 1; \ } CHECK_SIZE(struct dt_dt_s, uint128_t); CHECK_SIZE(struct dt_d_s, uint64_t); CHECK_SIZE(struct dt_t_s, uint64_t); CHECK_SIZE(dt_ymdhms_t, uint64_t); CHECK_SIZE(dt_sexy_t, uint64_t); return res; } /* struct-7.c ends here */ dateutils-0.4.5/test/struct-8.c000066400000000000000000000010051335042257000163270ustar00rootroot00000000000000#if defined HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include #include "date-core.h" int main(void) { int res = 0; #define CHECK_SIZE(x, y) \ if (sizeof(x) != sizeof(y)) { \ fprintf(stderr, "sizeof(" #x ") -> %zu\n", sizeof(x)); \ res = 1; \ } CHECK_SIZE(struct dt_d_s, uint64_t); CHECK_SIZE(dt_ymd_t, uint32_t); CHECK_SIZE(dt_ymcw_t, uint32_t); CHECK_SIZE(dt_bizda_t, uint32_t); CHECK_SIZE(dt_daisy_t, uint32_t); return res; } /* struct-8.c ends here */ dateutils-0.4.5/test/struct-9.c000066400000000000000000000007131335042257000163350ustar00rootroot00000000000000#if defined HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include #include "time-core.h" int main(void) { int res = 0; #define CHECK_SIZE(x, y) \ if (sizeof(x) != sizeof(y)) { \ fprintf(stderr, "sizeof(" #x ") -> %zu\n", sizeof(x)); \ res = 1; \ } CHECK_SIZE(struct dt_t_s, uint64_t); CHECK_SIZE(dt_hms_t, struct { uint64_t foo:56; } __attribute__((packed))); return res; } /* struct-9.c ends here */ dateutils-0.4.5/test/tadd.001.clit000066400000000000000000000001501335042257000165620ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dadd 10:01:00 1h6m 11:07:00 $ ## tadd.1.clit ends here dateutils-0.4.5/test/tadd.002.clit000066400000000000000000000001511335042257000165640ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dadd 10:01:00 -1h6m 08:55:00 $ ## tadd.2.clit ends here dateutils-0.4.5/test/tadd.003.clit000066400000000000000000000001511335042257000165650ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dadd 10:01:00 3605s 11:01:05 $ ## tadd.3.clit ends here dateutils-0.4.5/test/tadd.004.clit000066400000000000000000000002031335042257000165640ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dadd 12m <=12:00:00' <=12:00:00' < #include #include #include "time-core.h" #define CHECK_RES(rc, pred, args...) \ if (pred) { \ fprintf(stderr, args); \ res = rc; \ } #define CHECK(pred, args...) \ CHECK_RES(1, pred, args) #define CHECK_EQ(slot, val, args...) \ CHECK(slot != val, args, slot, val) static int add_chk(struct dt_t_s tes, struct dt_t_s ref) { int res = 0; CHECK(tes.typ != ref.typ, " TYPE DIFFERS %u ... should be %u\n", (unsigned int)tes.typ, (unsigned int)ref.typ); if (!ref.dur) { CHECK(tes.dur, " DURATION BIT SET\n"); } else { CHECK(!tes.dur, " DURATION BIT NOT SET\n"); } if (!ref.neg) { CHECK(tes.neg, " NEGATED BIT SET\n"); } else { CHECK(!tes.neg, " NEGATED BIT NOT SET\n"); } if (tes.typ == DT_HMS) { CHECK_EQ((unsigned int)tes.hms.h, (unsigned int)ref.hms.h, " HOUR %u ... should be %u\n"); CHECK_EQ((unsigned int)tes.hms.m, (unsigned int)ref.hms.m, " MINUTE %u ... should be %u\n"); CHECK_EQ((unsigned int)tes.hms.s, (unsigned int)ref.hms.s, " SECOND %u ... should be %u\n"); /* make sure the padding leaves no garbage */ CHECK_RES(res, tes.hms.u & ~0x1f3f3f3fffffff, " PADDING NOT NAUGHT %x\n", (unsigned int)(tes.hms.u & ~0x1f3f3f3fffffff)); } CHECK(tes.carry != ref.carry, " CARRY DIFFERS %d ... should be %d\n", (signed int)tes.carry, (signed int)ref.carry); return res; } int main(void) { int rc = 0; struct dt_t_s t; int dur; struct dt_t_s res; struct dt_t_s chk; /* 12:34:56 + 17s */ t = dt_t_initialiser(); t.typ = DT_HMS; t.hms.h = 12; t.hms.m = 34; t.hms.s = 56; dur = 17; /* should be 12:35:13 */ chk = dt_t_initialiser(); chk.typ = DT_HMS; chk.hms.h = 12; chk.hms.m = 35; chk.hms.s = 13; /* add, then check */ if (res = dt_tadd_s(t, dur, 0), add_chk(res, chk)) { rc = 1; } /* 12:34:56 + 11*3600s + 25*60s + 4s */ t = dt_t_initialiser(); t.typ = DT_HMS; t.hms.h = 12; t.hms.m = 34; t.hms.s = 56; dur = 11 * 3600 + 25 * 60 + 4; /* should be 00:00:00 */ chk = dt_t_initialiser(); chk.typ = DT_HMS; chk.hms.h = 00; chk.hms.m = 00; chk.hms.s = 00; chk.carry = 1; /* add, then check */ if (res = dt_tadd_s(t, dur, 0), add_chk(res, chk)) { rc = 1; } /* 12:34:56 + 11*3600s + 25*60s + 4s on a leap day */ t = dt_t_initialiser(); t.typ = DT_HMS; t.hms.h = 12; t.hms.m = 34; t.hms.s = 56; dur = 11 * 3600 + 25 * 60 + 4; /* should be 00:00:00 */ chk = dt_t_initialiser(); chk.typ = DT_HMS; chk.hms.h = 23; chk.hms.m = 59; chk.hms.s = 60; chk.carry = 0; /* add, then check */ if (res = dt_tadd_s(t, dur, 1), add_chk(res, chk)) { rc = 1; } /* 12:34:56 + 11*3600s + 25*60s + 3s on a -leap day */ t = dt_t_initialiser(); t.typ = DT_HMS; t.hms.h = 12; t.hms.m = 34; t.hms.s = 56; dur = 11 * 3600 + 25 * 60 + 3; /* should be 00:00:00 */ chk = dt_t_initialiser(); chk.typ = DT_HMS; chk.hms.h = 00; chk.hms.m = 00; chk.hms.s = 00; chk.carry = 1; /* add, then check */ if (res = dt_tadd_s(t, dur, -1), add_chk(res, chk)) { rc = 1; } /* 12:34:56 + 11*3600s + 25*60s + 2s on a -leap day */ t = dt_t_initialiser(); t.typ = DT_HMS; t.hms.h = 12; t.hms.m = 34; t.hms.s = 56; dur = 11 * 3600 + 25 * 60 + 2; /* should be 00:00:00 */ chk = dt_t_initialiser(); chk.typ = DT_HMS; chk.hms.h = 23; chk.hms.m = 59; chk.hms.s = 58; chk.carry = 0; /* add, then check */ if (res = dt_tadd_s(t, dur, -1), add_chk(res, chk)) { rc = 1; } /* 12:34:56 + 11*3600s + 25*60s + 3s on a +leap day */ t = dt_t_initialiser(); t.typ = DT_HMS; t.hms.h = 12; t.hms.m = 34; t.hms.s = 56; dur = 11 * 3600 + 25 * 60 + 3; /* should be 00:00:00 */ chk = dt_t_initialiser(); chk.typ = DT_HMS; chk.hms.h = 23; chk.hms.m = 59; chk.hms.s = 59; chk.carry = 0; /* add, then check */ if (res = dt_tadd_s(t, dur, 1), add_chk(res, chk)) { rc = 1; } return rc; } /* time-core-add.c ends here */ dateutils-0.4.5/test/tround.001.clit000066400000000000000000000002111335042257000171570ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dround 17:04:00 1m 18:01:00 $ dround 17:04:00 /1m 17:04:00 $ ## tround.1.clit ends here dateutils-0.4.5/test/tround.002.clit000066400000000000000000000002171335042257000171660ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dround -n 17:04:00 4m 18:04:00 $ dround -n 17:04:00 /1m 17:05:00 $ ## tround.2.clit ends here dateutils-0.4.5/test/tround.003.clit000066400000000000000000000002111335042257000171610ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dround 17:05:00 5m 17:05:00 $ dround 17:04:00 /5m 17:05:00 $ ## tround.3.clit ends here dateutils-0.4.5/test/tround.004.clit000066400000000000000000000002201335042257000171620ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dround -n 17:05:00 -5m 16:05:00 $ dround -n 17:04:00 /5m 17:05:00 $ ## tround.4.clit ends here dateutils-0.4.5/test/tround.005.clit000066400000000000000000000002201335042257000171630ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dround 17:05:00 -5m 17:05:00 $ dround -n 17:04:00 /-5m 17:00:00 $ ## tround.005.clit ends here dateutils-0.4.5/test/tround.006.clit000066400000000000000000000002161335042257000171710ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dround 17:05:00 -1m 17:01:00 $ dround 17:04:00 /-10m 17:00:00 $ ## tround.006.clit ends here dateutils-0.4.5/test/tseq.01.clit000066400000000000000000000002461335042257000165500ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 10:00:00 12m 11:20:00 10:00:00 10:12:00 10:24:00 10:36:00 10:48:00 11:00:00 11:12:00 $ ## tseq.1.clit ends here dateutils-0.4.5/test/tseq.02.clit000066400000000000000000000002721335042257000165500ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq --compute-from-last 10:00:00 12m 11:20:00 10:08:00 10:20:00 10:32:00 10:44:00 10:56:00 11:08:00 11:20:00 $ ## tseq.2.clit ends here dateutils-0.4.5/test/tseq.03.clit000066400000000000000000000002471335042257000165530ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 11:20:00 -12m 10:00:00 11:20:00 11:08:00 10:56:00 10:44:00 10:32:00 10:20:00 10:08:00 $ ## tseq.3.clit ends here dateutils-0.4.5/test/tseq.04.clit000066400000000000000000000002731335042257000165530ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq --compute-from-last 11:20:00 -12m 10:00:00 11:12:00 11:00:00 10:48:00 10:36:00 10:24:00 10:12:00 10:00:00 $ ## tseq.4.clit ends here dateutils-0.4.5/test/tseq.05.clit000066400000000000000000000011161335042257000165510ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 10:00:00 -12m 23:20:00 10:00:00 09:48:00 09:36:00 09:24:00 09:12:00 09:00:00 08:48:00 08:36:00 08:24:00 08:12:00 08:00:00 07:48:00 07:36:00 07:24:00 07:12:00 07:00:00 06:48:00 06:36:00 06:24:00 06:12:00 06:00:00 05:48:00 05:36:00 05:24:00 05:12:00 05:00:00 04:48:00 04:36:00 04:24:00 04:12:00 04:00:00 03:48:00 03:36:00 03:24:00 03:12:00 03:00:00 02:48:00 02:36:00 02:24:00 02:12:00 02:00:00 01:48:00 01:36:00 01:24:00 01:12:00 01:00:00 00:48:00 00:36:00 00:24:00 00:12:00 00:00:00 23:48:00 23:36:00 23:24:00 $ ## tseq.5.clit ends here dateutils-0.4.5/test/tseq.06.clit000066400000000000000000000011151335042257000165510ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 23:20:00 12m 10:00:00 23:20:00 23:32:00 23:44:00 23:56:00 00:08:00 00:20:00 00:32:00 00:44:00 00:56:00 01:08:00 01:20:00 01:32:00 01:44:00 01:56:00 02:08:00 02:20:00 02:32:00 02:44:00 02:56:00 03:08:00 03:20:00 03:32:00 03:44:00 03:56:00 04:08:00 04:20:00 04:32:00 04:44:00 04:56:00 05:08:00 05:20:00 05:32:00 05:44:00 05:56:00 06:08:00 06:20:00 06:32:00 06:44:00 06:56:00 07:08:00 07:20:00 07:32:00 07:44:00 07:56:00 08:08:00 08:20:00 08:32:00 08:44:00 08:56:00 09:08:00 09:20:00 09:32:00 09:44:00 09:56:00 $ ## tseq.6.clit ends here dateutils-0.4.5/test/tseq.07.clit000066400000000000000000000002701335042257000165530ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 23:20:00 20m 02:00:00 23:20:00 23:40:00 00:00:00 00:20:00 00:40:00 01:00:00 01:20:00 01:40:00 02:00:00 $ ## tseq.7.clit ends here dateutils-0.4.5/test/tseq.08.clit000066400000000000000000000002711335042257000165550ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 02:00:00 -20m 23:20:00 02:00:00 01:40:00 01:20:00 01:00:00 00:40:00 00:20:00 00:00:00 23:40:00 23:20:00 $ ## tseq.8.clit ends here dateutils-0.4.5/test/tseq.09.clit000066400000000000000000000003131335042257000165530ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 02:00:00 +30m 07:00:00 02:00:00 02:30:00 03:00:00 03:30:00 04:00:00 04:30:00 05:00:00 05:30:00 06:00:00 06:30:00 07:00:00 $ ## tseq.9.clit ends here dateutils-0.4.5/test/tseq.10.clit000066400000000000000000000002371335042257000165500ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 02:00:00 +60m 07:00:00 02:00:00 03:00:00 04:00:00 05:00:00 06:00:00 07:00:00 $ ## tseq.10.clit ends here dateutils-0.4.5/test/tseq.11.clit000066400000000000000000000002361335042257000165500ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 02:00:00 +1h 07:00:00 02:00:00 03:00:00 04:00:00 05:00:00 06:00:00 07:00:00 $ ## tseq.11.clit ends here dateutils-0.4.5/test/tseq.12.clit000066400000000000000000000004701335042257000165510ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 01:00:00 +60m 23:00:00 01:00:00 02:00:00 03:00:00 04:00:00 05:00:00 06:00:00 07:00:00 08:00:00 09:00:00 10:00:00 11:00:00 12:00:00 13:00:00 14:00:00 15:00:00 16:00:00 17:00:00 18:00:00 19:00:00 20:00:00 21:00:00 22:00:00 23:00:00 $ ## tseq.12.clit ends here dateutils-0.4.5/test/tseq.13.clit000066400000000000000000000004671335042257000165600ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 01:00:00 +1h 23:00:00 01:00:00 02:00:00 03:00:00 04:00:00 05:00:00 06:00:00 07:00:00 08:00:00 09:00:00 10:00:00 11:00:00 12:00:00 13:00:00 14:00:00 15:00:00 16:00:00 17:00:00 18:00:00 19:00:00 20:00:00 21:00:00 22:00:00 23:00:00 $ ## tseq.13.clit ends here dateutils-0.4.5/test/tseq.14.clit000066400000000000000000000004701335042257000165530ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 01:20:00 +60m 23:20:00 01:20:00 02:20:00 03:20:00 04:20:00 05:20:00 06:20:00 07:20:00 08:20:00 09:20:00 10:20:00 11:20:00 12:20:00 13:20:00 14:20:00 15:20:00 16:20:00 17:20:00 18:20:00 19:20:00 20:20:00 21:20:00 22:20:00 23:20:00 $ ## tseq.14.clit ends here dateutils-0.4.5/test/tseq.15.clit000066400000000000000000000004671335042257000165620ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 01:20:00 +1h 23:20:00 01:20:00 02:20:00 03:20:00 04:20:00 05:20:00 06:20:00 07:20:00 08:20:00 09:20:00 10:20:00 11:20:00 12:20:00 13:20:00 14:20:00 15:20:00 16:20:00 17:20:00 18:20:00 19:20:00 20:20:00 21:20:00 22:20:00 23:20:00 $ ## tseq.15.clit ends here dateutils-0.4.5/test/tseq.16.clit000066400000000000000000000005001335042257000165470ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 01:00:00 +1h 00:00:00 01:00:00 02:00:00 03:00:00 04:00:00 05:00:00 06:00:00 07:00:00 08:00:00 09:00:00 10:00:00 11:00:00 12:00:00 13:00:00 14:00:00 15:00:00 16:00:00 17:00:00 18:00:00 19:00:00 20:00:00 21:00:00 22:00:00 23:00:00 00:00:00 $ ## tseq.16.clit ends here dateutils-0.4.5/test/tseq.17.clit000066400000000000000000000005001335042257000165500ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 01:00:00 -1h 02:00:00 01:00:00 00:00:00 23:00:00 22:00:00 21:00:00 20:00:00 19:00:00 18:00:00 17:00:00 16:00:00 15:00:00 14:00:00 13:00:00 12:00:00 11:00:00 10:00:00 09:00:00 08:00:00 07:00:00 06:00:00 05:00:00 04:00:00 03:00:00 02:00:00 $ ## tseq.17.clit ends here dateutils-0.4.5/test/tseq.18.clit000066400000000000000000000005111335042257000165530ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 01:00:00 +1h 01:00:00 01:00:00 02:00:00 03:00:00 04:00:00 05:00:00 06:00:00 07:00:00 08:00:00 09:00:00 10:00:00 11:00:00 12:00:00 13:00:00 14:00:00 15:00:00 16:00:00 17:00:00 18:00:00 19:00:00 20:00:00 21:00:00 22:00:00 23:00:00 00:00:00 01:00:00 $ ## tseq.18.clit ends here dateutils-0.4.5/test/tseq.19.clit000066400000000000000000000005111335042257000165540ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dseq 01:00:00 -1h 01:00:00 01:00:00 00:00:00 23:00:00 22:00:00 21:00:00 20:00:00 19:00:00 18:00:00 17:00:00 16:00:00 15:00:00 14:00:00 13:00:00 12:00:00 11:00:00 10:00:00 09:00:00 08:00:00 07:00:00 06:00:00 05:00:00 04:00:00 03:00:00 02:00:00 01:00:00 $ ## tseq.19.clit ends here dateutils-0.4.5/test/ttest.001.clit000066400000000000000000000001761335042257000170210ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dtest 12:00:04 --gt 11:22:33 && echo "true" true $ ## ttest.1.clit ends here dateutils-0.4.5/test/ttest.002.clit000066400000000000000000000002001335042257000170060ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dtest 12:00:04 --lt 11:22:33 || echo "false" false $ ## ttest.2.clit ends here dateutils-0.4.5/test/ttest.003.clit000066400000000000000000000001721335042257000170170ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dtest 12:00:04 --cmp 11:22:33; echo "${?}" 1 $ ## ttest.3.clit ends here dateutils-0.4.5/test/ttest.004.clit000066400000000000000000000001721335042257000170200ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dtest --cmp 11:22:33 12:00:04; echo "${?}" 2 $ ## ttest.4.clit ends here dateutils-0.4.5/test/ttest.005.clit000066400000000000000000000001721335042257000170210ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dtest --cmp 11:22:33 11:22:33; echo "${?}" 0 $ ## ttest.5.clit ends here dateutils-0.4.5/test/ttest.006.clit000066400000000000000000000001761335042257000170260ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dtest --eq 11:22:33 11:22:33 && echo "true" true $ ## ttest.6.clit ends here dateutils-0.4.5/test/ttest.007.clit000066400000000000000000000002001335042257000170130ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dtest --ne 11:22:33 11:22:33 || echo "false" false $ ## ttest.7.clit ends here dateutils-0.4.5/test/tzmap.001.clit000066400000000000000000000002311335042257000170010ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dzone dummy:XETR 2012-03-04T12:04:11 2012-03-04T13:04:11+01:00 dummy:XETR $ ## tzmap.001.clit ends here dateutils-0.4.5/test/tzmap.002.clit000066400000000000000000000002241335042257000170040ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dconv --from-zone dummy:XETR 2012-03-04T12:04:11 2012-03-04T11:04:11 $ ## tzmap.002.clit ends here dateutils-0.4.5/test/tzmap.003.clit000066400000000000000000000002601335042257000170050ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dzone dummy:XETR --from-zone dummy:XLON 2012-03-04T12:04:11 2012-03-04T13:04:11+01:00 dummy:XETR $ ## tzmap.003.clit ends here dateutils-0.4.5/test/tzmap.004.clit000066400000000000000000000002541335042257000170110ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ dadd --zone dummy:XETR --from-zone Europe/London 2012-03-04T12:04:11 +1h 2012-03-04T14:04:11 $ ## tzmap.004.clit ends here dateutils-0.4.5/test/tzmap_check_01.clit000066400000000000000000000002671335042257000201500ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ ignore-return find "${root}/lib" "${TZMAP_DIR}/../lib" -name '*.tzmap' | \ xargs "${TZMAP}" check $ ## tzmap_check_01.clit ends here dateutils-0.4.5/test/tzmap_check_02.clit000066400000000000000000000002461335042257000201460ustar00rootroot00000000000000#!/usr/bin/clitoris ## -*- shell-script -*- $ find "${root}/lib" "${TZMAP_DIR}/../lib" -name '*.tzmcc' | xargs "${TZMAP}" check $ ## tzmap_check_02.clit ends here dateutils-0.4.5/version.mk.in000066400000000000000000000001421335042257000161370ustar00rootroot00000000000000VERSION = YUCK_SCMVER_VERSION PACKAGE_VERSION = $(VERSION) PACKAGE_STRING = $(PACKAGE) $(VERSION)