DUMMYPOFILES = @DUMMYPOFILES@
DISTFILES.common = Makefile.in.in Makevars remove-potcdate.sin \
$(DISTFILES.common.extra1) $(DISTFILES.common.extra2) $(DISTFILES.common.extra3)
-DISTFILES = $(DISTFILES.common) POTFILES.in $(DOMAIN).pot \
+DISTFILES = $(DISTFILES.common) POTFILES.in $(DOMAIN).pot stamp-po \
$(POFILES) $(GMOFILES) \
$(DISTFILES.extra1) $(DISTFILES.extra2) $(DISTFILES.extra3)
all: all-@USE_NLS@
-all-yes: $(CATALOGS)
+all-yes: stamp-po
all-no:
+# stamp-po is a timestamp denoting the last time at which the CATALOGS have
+# been loosely updated. Its purpose is that when a developer or translator
+# checks out the package via CVS, and the $(DOMAIN).pot file is not in CVS,
+# "make" will update the $(DOMAIN).pot and the $(CATALOGS), but subsequent
+# invocations of "make" will do nothing. This timestamp would not be necessary
+# if updating the $(CATALOGS) would always touch them; however, the rule for
+# $(POFILES) has been designed to not touch files that don't need to be
+# changed.
+stamp-po: $(srcdir)/$(DOMAIN).pot
+ $(MAKE) $(CATALOGS)
+ @echo "touch stamp-po"
+ @echo timestamp > stamp-poT
+ @mv stamp-poT stamp-po
+
# Note: Target 'all' must not depend on target '$(DOMAIN).pot-update',
# otherwise packages like GCC can not be built if only parts of the source
# have been downloaded.
+# This target rebuilds $(DOMAIN).pot; it is an expensive operation.
+# Note that $(DOMAIN).pot is not touched if it doesn't need to be changed.
$(DOMAIN).pot-update: $(POTFILES) $(srcdir)/POTFILES.in remove-potcdate.sed
$(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \
--add-comments=TRANSLATORS: $(XGETTEXT_OPTIONS) \
fi; \
}
+# This rule has no dependencies: we don't need to update $(DOMAIN).pot at
+# every "make" invocation, only create it when it is missing.
+# Only "make $(DOMAIN).pot-update" or "make dist" will force an update.
$(srcdir)/$(DOMAIN).pot:
$(MAKE) $(DOMAIN).pot-update
+# This target rebuilds a PO file if $(DOMAIN).pot has changed.
+# Note that a PO file is not touched if it doesn't need to be changed.
$(POFILES): $(srcdir)/$(DOMAIN).pot
@lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \
test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
mostlyclean:
rm -f remove-potcdate.sed
+ rm -f stamp-poT
rm -f core core.* $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.new.po
rm -fr *.o
maintainer-clean: distclean
@echo "This command is intended for maintainers to use;"
@echo "it deletes files that may require special tools to rebuild."
- rm -f $(GMOFILES)
+ rm -f stamp-po $(GMOFILES)
distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
dist distdir:
/* Message list test for equality.
- Copyright (C) 2001 Free Software Foundation, Inc.
+ Copyright (C) 2001-2002 Free Software Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software; you can redistribute it and/or modify
/* Specification. */
#include "msgl-equal.h"
+#include <stddef.h>
#include <string.h>
/* Prototypes for local functions. Needed to ensure compiler checking of
function argument counts despite of K&R C function definition syntax. */
+static inline bool msgstr_equal PARAMS ((const char *msgstr1,
+ size_t msgstr1_len,
+ const char *msgstr2,
+ size_t msgstr2_len));
+static inline bool msgstr_equal_ignoring_potcdate PARAMS ((const char *msgstr1,
+ size_t msgstr1_len,
+ const char *msgstr2,
+ size_t msgstr2_len));
static inline bool pos_equal PARAMS ((const lex_pos_ty *pos1,
const lex_pos_ty *pos2));
static inline bool msgdomain_equal PARAMS ((const msgdomain_ty *mdp1,
- const msgdomain_ty *mdp2));
+ const msgdomain_ty *mdp2,
+ bool ignore_potcdate));
+static inline bool
+msgstr_equal (msgstr1, msgstr1_len, msgstr2, msgstr2_len)
+ const char *msgstr1;
+ size_t msgstr1_len;
+ const char *msgstr2;
+ size_t msgstr2_len;
+{
+ return (msgstr1_len == msgstr2_len
+ && memcmp (msgstr1, msgstr2, msgstr1_len) == 0);
+}
+
+static bool
+msgstr_equal_ignoring_potcdate (msgstr1, msgstr1_len, msgstr2, msgstr2_len)
+ const char *msgstr1;
+ size_t msgstr1_len;
+ const char *msgstr2;
+ size_t msgstr2_len;
+{
+ const char *msgstr1_end = msgstr1 + msgstr1_len;
+ const char *msgstr2_end = msgstr2 + msgstr2_len;
+ const char *ptr1;
+ const char *ptr2;
+ const char *const field = "POT-Creation-Date:";
+ const ptrdiff_t fieldlen = sizeof ("POT-Creation-Date:") - 1;
+
+ /* Search for the occurrence of field in msgstr1. */
+ for (ptr1 = msgstr1;;)
+ {
+ if (msgstr1_end - ptr1 < fieldlen)
+ {
+ ptr1 = NULL;
+ break;
+ }
+ if (memcmp (ptr1, field, fieldlen) == 0)
+ break;
+ ptr1 = memchr (ptr1, '\n', msgstr1_end - ptr1);
+ if (ptr1 == NULL)
+ break;
+ ptr1++;
+ }
+
+ /* Search for the occurrence of field in msgstr2. */
+ for (ptr2 = msgstr2;;)
+ {
+ if (msgstr2_end - ptr2 < fieldlen)
+ {
+ ptr2 = NULL;
+ break;
+ }
+ if (memcmp (ptr2, field, fieldlen) == 0)
+ break;
+ ptr2 = memchr (ptr2, '\n', msgstr2_end - ptr2);
+ if (ptr2 == NULL)
+ break;
+ ptr2++;
+ }
+
+ if (ptr1 == NULL)
+ {
+ if (ptr2 == NULL)
+ return msgstr_equal (msgstr1, msgstr1_len, msgstr2, msgstr2_len);
+ }
+ else
+ {
+ if (ptr2 != NULL)
+ {
+ /* Compare, ignoring the lines starting at ptr1 and ptr2. */
+ if (msgstr_equal (msgstr1, ptr1 - msgstr1, msgstr2, ptr2 - msgstr2))
+ {
+ ptr1 = memchr (ptr1, '\n', msgstr1_end - ptr1);
+ if (ptr1 == NULL)
+ ptr1 = msgstr1_end;
+
+ ptr2 = memchr (ptr2, '\n', msgstr2_end - ptr2);
+ if (ptr2 == NULL)
+ ptr2 = msgstr2_end;
+
+ return msgstr_equal (ptr1, msgstr1_end - ptr1,
+ ptr2, msgstr2_end - ptr2);
+ }
+ }
+ }
+ return false;
+}
+
static inline bool
pos_equal (pos1, pos2)
const lex_pos_ty *pos1;
}
bool
-message_equal (mp1, mp2)
+message_equal (mp1, mp2, ignore_potcdate)
const message_ty *mp1;
const message_ty *mp2;
+ bool ignore_potcdate;
{
size_t i, i1, i2;
: mp2->msgid_plural == NULL))
return false;
- if (mp1->msgstr_len != mp2->msgstr_len)
- return false;
- if (memcmp (mp1->msgstr, mp2->msgstr, mp1->msgstr_len) != 0)
+ if (mp1->msgid[0] == '\0' && ignore_potcdate
+ ? !msgstr_equal_ignoring_potcdate (mp1->msgstr, mp1->msgstr_len,
+ mp2->msgstr, mp2->msgstr_len)
+ : !msgstr_equal (mp1->msgstr, mp1->msgstr_len,
+ mp2->msgstr, mp2->msgstr_len))
return false;
if (!pos_equal (&mp1->pos, &mp2->pos))
}
bool
-message_list_equal (mlp1, mlp2)
+message_list_equal (mlp1, mlp2, ignore_potcdate)
const message_list_ty *mlp1;
const message_list_ty *mlp2;
+ bool ignore_potcdate;
{
size_t i, i1, i2;
if (i1 != i2)
return false;
for (i = 0; i < i1; i++)
- if (!message_equal (mlp1->item[i], mlp2->item[i]))
+ if (!message_equal (mlp1->item[i], mlp2->item[i], ignore_potcdate))
return false;
return true;
}
static inline bool
-msgdomain_equal (mdp1, mdp2)
+msgdomain_equal (mdp1, mdp2, ignore_potcdate)
const msgdomain_ty *mdp1;
const msgdomain_ty *mdp2;
+ bool ignore_potcdate;
{
return (strcmp (mdp1->domain, mdp2->domain) == 0
- && message_list_equal (mdp1->messages, mdp2->messages));
+ && message_list_equal (mdp1->messages, mdp2->messages,
+ ignore_potcdate));
}
bool
-msgdomain_list_equal (mdlp1, mdlp2)
+msgdomain_list_equal (mdlp1, mdlp2, ignore_potcdate)
const msgdomain_list_ty *mdlp1;
const msgdomain_list_ty *mdlp2;
+ bool ignore_potcdate;
{
size_t i, i1, i2;
if (i1 != i2)
return false;
for (i = 0; i < i1; i++)
- if (!msgdomain_equal (mdlp1->item[i], mdlp2->item[i]))
+ if (!msgdomain_equal (mdlp1->item[i], mdlp2->item[i], ignore_potcdate))
return false;
return true;
}
/* Message list test for equality.
- Copyright (C) 2001 Free Software Foundation, Inc.
+ Copyright (C) 2001-2002 Free Software Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software; you can redistribute it and/or modify
would be the same. */
extern bool
- message_equal PARAMS ((const message_ty *mp1, const message_ty *mp2));
+ message_equal PARAMS ((const message_ty *mp1, const message_ty *mp2,
+ bool ignore_potcdate));
extern bool
message_list_equal PARAMS ((const message_list_ty *mlp1,
- const message_list_ty *mlp2));
+ const message_list_ty *mlp2,
+ bool ignore_potcdate));
extern bool
msgdomain_list_equal PARAMS ((const msgdomain_list_ty *mdlp1,
- const msgdomain_list_ty *mdlp2));
+ const msgdomain_list_ty *mdlp2,
+ bool ignore_potcdate));
#endif /* _MSGL_EQUAL_H */