.ONESHELL:
.SHELLFLAGS := -ec
+# Recipes which redirect stdout to the target of the rule (i.e., constructs
+# like cmd > $@) create empty or incomplete output files if the command fails,
+# for example when cmd was not found. Since the target exists and is uptodate
+# in this case, this may lead to all sorts of problems. The following target
+# makes sure that such files are removed.
+.DELETE_ON_ERROR:
+
PREFIX ?= /usr/local
M4 := m4
LN := ln -f
GROFF := groff
CP := cp
INSTALL := install
-GZIP := gzip -f9
+GZIP := gzip -fn9
ZCAT := zcat
+CC += -ffile-prefix-map=$(CURDIR)=.
+
+dummy != $(M4) /dev/null || printf 'failed'
+ifeq ($(dummy), failed)
+$(error m4 is required to build this package)
+endif
+dummy != printf '%%%%\n' | $(LEX) -o /dev/null || printf 'failed'
+ifeq ($(dummy), failed)
+$(error (f)lex is required to build this package)
+endif
+
DATE_FMT := +%B %Y
# To get a reproducible build, we use $(SOURCE_DATE_EPOCH) instead of the
# current time if this variable is set.
liblopsub_objs := config_file.o lopsub.o version.o
lopsubex_objs := lopsubex.o lopsubex.lsg.o $(liblopsub_objs)
+LLS_CFLAGS := -g -fPIC
+STRICT_CFLAGS := -Wall
+STRICT_CFLAGS += -Werror-implicit-function-declaration
+
$(lsg_objs) $(liblopsub_objs) $(lopsubex_objs): %.o: %.c
lopsubgen.o config_file.o:
- $(CC) -g -c -fPIC -o $@ ${@:.o=.c}
+ $(CC) $(CPPFLAGS) $(LLS_CFLAGS) $(CFLAGS) -c -o $@ ${@:.o=.c}
lsg1.o: lsg.c lsg.h
- $(CC) -g -DSTAGE1 -Wall -g -c $< -o $@
+ $(CC) $(CPPFLAGS) $(LLS_CFLAGS) $(STRICT_CFLAGS) $(CFLAGS) -DSTAGE1 -c -o $@ $<
%.o: %.c
- $(CC) -Wall -I. -g -c -fPIC -o $@ $<
+ $(CC) -I. $(CPPFLAGS) $(LLS_CFLAGS) $(STRICT_CFLAGS) $(CFLAGS) -c -o $@ $<
# linking
lopsubgen-stage1: $(lsg1_objs)
$(CC) -Wall -g -o $@ $(lsg_objs)
$(REALNAME): $(liblopsub_objs)
$(CC) --shared -Wl,-soname,liblopsub.so.$(MAJOR_VERSION) -o $@ $^
+liblopsub.a: $(liblopsub_objs)
+ $(AR) -rcs $@ $^
+
lopsubex: $(lopsubex_objs) $(REALNAME)
$(CC) -Wall -g -o $@ $(lopsubex_objs)
# web
html := $(addprefix web/, $(addsuffix .html, \
- index lopsub-api lopsubgen.1 lopsubex.1 $(m4_man_pages)))
-$(html): $(addprefix web/, $(addsuffix .html, header footer))
-
+ index lopsub-api lopsubgen.1 lopsubex.1 $(m4_man_pages:.gz=)))
www: $(html)
-
-web/lopsub-api.html: lopsub.h.m4
+web/lopsub-api.html: lopsub.h.m4 web/header.html web/footer.html
$(M4) -DOUTPUT_MODE=HTML web/header.html $(gendoc) \
$< web/footer.html > $@
web/index.html: web/lopsub.7.html
$(LN) -s $(notdir $<) $@
-web/%.html: %.gz
+web/%.html: %.gz web/header.html
$(CP) web/header.html $@
$(ZCAT) $< | $(GROFF) -m man -Thtml | sed -e '1,/^<body>/d' >> $@
distclean: clean
$(RM) *.lsg.c *.lsg.h lopsubgen.c config_file.c lopsubgen-stage1 \
lopsub.h lopsub.7 lopsub-suite.5 version.c
-
+-include Makefile.local
+Noteworthy changes in lopsub-1.0.4 (2023-07-02)
+===============================================
+* make the build reproducible (Chris Lamb, Vagrant Cascadian)
+* improvements to the build system
+* documentation fixes
+* avoid NULL pointer dereference in argument parsing
+
Noteworthy changes in lopsub-1.0.3 (2019-05-19)
===============================================
* build a shared library instead of a static one
%s SC_SCANNING
IDENTIFIER [a-zA-Z]+[a-zA-Z0-9_-]*
-EQUALS [[:space:]]*=[[:space:]]*
+EQUALS [[:blank:]]*=[[:blank:]]*
OPTION [a-zA-Z]+[a-zA-Z0-9_-]*
%{
%%
/* skip comments and whitespace */
-^[[:space:]]*#.*\n ;
-[[:space:]]|\n+ ;
+^[[:blank:]]*#.*\n ;
+[[:blank:]]|\n+ ;
-<INITIAL,SC_SCANNING>\[[[:space:]]*{IDENTIFIER}[[:space:]]*\][[:space:]]*\n {
+<INITIAL,SC_SCANNING>\[[[:blank:]]*{IDENTIFIER}[[:blank:]]*\][[:blank:]]*\n {
int i, j;
const char *subcmd = yyget_extra(yyscanner)->subcmd;
BEGIN(SC_SCANNING);
}
-<SC_SCANNING>{OPTION}[[:space:]]*\n add_option(yyscanner);
+<SC_SCANNING>{OPTION}[[:blank:]]*\n add_option(yyscanner);
-<SC_SCANNING>{OPTION}({EQUALS}|[[:space:]]+) {
+<SC_SCANNING>{OPTION}({EQUALS}|[[:blank:]]+) {
int ret = add_option(yyscanner);
if (ret < 0)
if (errctx) {
*errctx = malloc(100);
if (*errctx)
- sprintf(*errctx, "error at line %d",
- yyget_lineno(yyscanner));
+ sprintf(*errctx, "yylex error");
}
}
yy_delete_buffer(yybs, yyscanner);
}
#if 0
+/* flex -o t.c config_file.l && cc -o tcf t.c */
int main(void)
{
char buf[100 * 1024];
exit(EXIT_FAILURE);
argc = ret;
for (i = 0; i < argc; i++)
- printf("argv[%d]: %s\n", i, rargv[i]);
+ printf("argv[%d]: %s\n", i, argv[i]);
return EXIT_SUCCESS;
}
#endif
+liblopsub (1.0.4-1.1) unstable; urgency=medium
+
+ * Non-maintainer upload.
+ * Rename libraries for 64-bit time_t transition. Closes: #1062407
+
+ -- Steve Langasek <vorlon@debian.org> Fri, 01 Mar 2024 05:37:06 +0000
+
+liblopsub (1.0.4-1) unstable; urgency=low
+
+ * Make the build reproducible (Chris Lamb, Vagrant Cascadian). Closes:
+ #1039617, #1039618
+ * Avoid crash due to a NULL pointer dereference in certain cases
+ * Minor cleanups and fixes, see NEWS for details.
+
+ -- Andre Noll <maan@tuebingen.mpg.de> Sun, 02 Jul 2023 14:12:13 +0200
+
liblopsub (1.0.3-2) unstable; urgency=low
* Make the output of lopsubgen reproducible.
Section: libdevel
Priority: optional
Maintainer: Andre Noll <maan@tuebingen.mpg.de>
-Build-Depends: m4, flex, debhelper (>= 10.0)
+Build-Depends: dpkg-dev (>= 1.22.5), m4, flex, debhelper (>= 10.0)
Standards-Version: 4.3.0
Homepage: http://people.tuebingen.mpg.de/maan/lopsub
Vcs-Browser: http://git.tuebingen.mpg.de/lopsub.git
Vcs-Git: git://git.tuebingen.mpg.de/lopsub.git
-Package: liblopsub1
+Package: liblopsub1t64
+Provides: ${t64:Provides}
+Replaces: liblopsub1
+Breaks: liblopsub1 (<< ${source:Version})
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: Long Option Parser for Subcommands
Package: liblopsub-dev
Architecture: any
-Depends: ${shlibs:Depends}, liblopsub1 (= ${binary:Version}), ${misc:Depends}
+Depends: ${shlibs:Depends}, liblopsub1t64 (= ${binary:Version}), ${misc:Depends}
Description: Long Option Parser for Subcommand - headers
Lopsub is an open source library written in C which aims to ease
the task of creating, documenting and parsing the options of Unix
-Copyright 2016 Andre Noll <maan@tuebingen.mpg.de>
+Copyright 2016-2023 Andre Noll <maan@tuebingen.mpg.de>
This package is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License, version 3
+++ /dev/null
-debian/tmp/usr/share/man/man7/*
-debian/tmp/usr/lib/*/liblopsub.so.*
# invoked with the package root as the current directory.
sourcepackage := liblopsub
-package := liblopsub1
+package := liblopsub1t64
devpackage := liblopsub-dev
define checkdir
$(INST_FILE) debian/copyright $(DEVDOCS_DIR)/copyright
$(INST_FILE) debian/changelog $(DOCS_DIR)/changelog.Debian
$(INST_FILE) debian/changelog $(DEVDOCS_DIR)/changelog.Debian
- gzip -f9 $(DOCS_DIR)/changelog.Debian
- gzip -f9 $(DEVDOCS_DIR)/changelog.Debian
+ gzip -fn9 $(DOCS_DIR)/changelog.Debian
+ gzip -fn9 $(DEVDOCS_DIR)/changelog.Debian
dh_makeshlibs
dh_shlibdeps
dh_strip
Supercommands and subcommands share the same set of possible command
directives. They differ mainly in the way the documentation is
-formated. There can only be one supercommand but arbitrary many
+formatted. There can only be one supercommand but arbitrary many
subcommands. For example, the supercommand could be the name of
the application, and the subcommands could be "load", "save" "info"
and "quit". The subcommand would be passed as the first non-option
and
.BR [/conclusion] .
Both texts will become part of the manual page, but are not not part
-of the short or long help. Like for the
-.B section
-directive, arbitrary roff source may be included here.
+of the short or long help.
.TP
.B aux_info_prefix
This text is shown at the bottom of each command before the value of the
return 0;
}
-/* Print a formated message to a dynamically allocated string. */
+/* Print a formatted message to a dynamically allocated string. */
__attribute__ ((format (printf, 2, 0)))
static int xvasprintf(char **result, const char *fmt, va_list ap)
{
bool multiple;
int idx, ret;
- if (!la->arg)
- goto success;
- if (opt->arg_info == LLS_NO_ARGUMENT) {
+ if (la->arg && opt->arg_info == LLS_NO_ARGUMENT) {
xasprintf(errctx, "arg: %s, option: %s", la->arg, opt->name);
return -E_LLS_ARG_GIVEN;
}
multiple = opt->flags & LLS_MULTIPLE;
+ if (opt->arg_type == LLS_STRING && !opt->values && !multiple) {
+ if (lor->value) { /* discard previous value */
+ free(lor->value[0].string_val);
+ free(lor->value);
+ lor->value = NULL;
+ }
+ }
+ if (!la->arg)
+ goto success;
idx = multiple? lor->given : 0;
- if (lor->given == 0 || multiple) {
- ret = xrealloc(&lor->value,
- (lor->given + 1) * sizeof(*lor->value));
+ if (!lor->value || multiple) {
+ ret = xrealloc(&lor->value, (idx + 1) * sizeof(*lor->value));
if (ret < 0) {
xasprintf(errctx, "option value array for --%s",
opt->name);
}
switch (opt->arg_type) {
case LLS_STRING:
- if (!opt->values && lor->given > 0 && !multiple)
- free(lor->value[idx].string_val);
if (opt->values) {
ret = check_enum_arg(la->arg, opt, errctx);
if (ret < 0)
xasprintf(errctx, "no non-option args allowed, "
"%u given", lpr->num_inputs);
else
- xasprintf(errctx, "%s %u non-option args allowed, "
- "%u given", min_argc < max_argc?
- "at most" : "exactly",
- max_argc, lpr->num_inputs);
+ xasprintf(errctx, "%s %u non-option args %s, %u given",
+ min_argc < max_argc? "at most" : "exactly",
+ max_argc,
+ min_argc < max_argc? "allowed" : "required",
+ lpr->num_inputs);
return -E_LLS_BAD_ARG_COUNT;
}
return 1;
exit(EXIT_FAILURE);
}
if (CUROPT.default_val) {
- fprintf(stderr, "value list must preceed default value\n");
+ fprintf(stderr, "value list must precede default value\n");
exit(EXIT_FAILURE);
}
BEGIN(SC_VALUES_ID);