From 8e8c32953ba65fadd3c99313b4988e4bfc835732 Mon Sep 17 00:00:00 2001 From: Jaakko Heinonen Date: Tue, 2 Oct 2001 18:11:10 +0000 Subject: [PATCH] Initial import --- depcomp | 411 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ getname.c | 357 +++++++++++++++++++++++++++++++++++++++++++++++ getname.h | 9 ++ 3 files changed, 777 insertions(+) create mode 100755 depcomp create mode 100644 getname.c create mode 100644 getname.h diff --git a/depcomp b/depcomp new file mode 100755 index 0000000..6589965 --- /dev/null +++ b/depcomp @@ -0,0 +1,411 @@ +#! /bin/sh + +# depcomp - compile a program generating dependencies as side-effects +# Copyright 1999, 2000 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Originally written by Alexandre Oliva . + +if test -z "$depmode" || test -z "$source" || test -z "$object"; then + echo "depcomp: Variables source, object and depmode must be set" 1>&2 + exit 1 +fi +# `libtool' can also be set to `yes' or `no'. + +depfile=${depfile-`echo "$object" | sed 's,\([^/]*\)$,.deps/\1,;s/\.\([^.]*\)$/.P\1/'`} +tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} + +rm -f "$tmpdepfile" + +# Some modes work just like other modes, but use different flags. We +# parameterize here, but still list the modes in the big case below, +# to make depend.m4 easier to write. Note that we *cannot* use a case +# here, because this file can only contain one case statement. +if test "$depmode" = hp; then + # HP compiler uses -M and no extra arg. + gccflag=-M + depmode=gcc +fi + +if test "$depmode" = dashXmstdout; then + # This is just like dashmstdout with a different argument. + dashmflag=-xM + depmode=dashmstdout +fi + +case "$depmode" in +gcc3) +## gcc 3 implements dependency tracking that does exactly what +## we want. Yay! Note: for some reason libtool 1.4 doesn't like +## it if -MD -MP comes after the -MF stuff. Hmm. + "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + mv "$tmpdepfile" "$depfile" + ;; + +gcc) +## There are various ways to get dependency output from gcc. Here's +## why we pick this rather obscure method: +## - Don't want to use -MD because we'd like the dependencies to end +## up in a subdir. Having to rename by hand is ugly. +## (We might end up doing this anyway to support other compilers.) +## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like +## -MM, not -M (despite what the docs say). +## - Using -M directly means running the compiler twice (even worse +## than renaming). + if test -z "$gccflag"; then + gccflag=-MD, + fi + "$@" -Wp,"$gccflag$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz +## The second -e expression handles DOS-style file names with drive letters. + sed -e 's/^[^:]*: / /' \ + -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" +## This next piece of magic avoids the `deleted header file' problem. +## The problem is that when a header file which appears in a .P file +## is deleted, the dependency causes make to die (because there is +## typically no way to rebuild the header). We avoid this by adding +## dummy dependencies for each header file. Too bad gcc doesn't do +## this for us directly. + tr ' ' ' +' < "$tmpdepfile" | +## Some versions of gcc put a space before the `:'. On the theory +## that the space means something, we add a space to the output as +## well. +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +sgi) + if test "$libtool" = yes; then + "$@" "-Wp,-MDupdate,$tmpdepfile" + else + "$@" -MDupdate "$tmpdepfile" + fi + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + + if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files + echo "$object : \\" > "$depfile" + + # Clip off the initial element (the dependent). Don't try to be + # clever and replace this with sed code, as IRIX sed won't handle + # lines with more than a fixed number of characters (4096 in + # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; + # the IRIX cc adds comments like `#:fec' to the end of the + # dependency line. + tr ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ + tr ' +' ' ' >> $depfile + echo >> $depfile + + # The second pass generates a dummy entry for each header file. + tr ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ + >> $depfile + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +aix) + # The C for AIX Compiler uses -M and outputs the dependencies + # in a .u file. This file always lives in the current directory. + # Also, the AIX compiler puts `$object:' at the start of each line; + # $object doesn't have directory information. + stripped=`echo "$object" | sed -e 's,^.*/,,' -e 's/\(.*\)\..*$/\1/'` + tmpdepfile="$stripped.u" + outname="$stripped.o" + if test "$libtool" = yes; then + "$@" -Wc,-M + else + "$@" -M + fi + + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + + if test -f "$tmpdepfile"; then + # Each line is of the form `foo.o: dependent.h'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile" + sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile" + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +tru64) + # The Tru64 AIX compiler uses -MD to generate dependencies as a side + # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. + # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put + # dependencies in `foo.d' instead, so we check for that too. + # Subdirectories are respected. + + tmpdepfile1="$object.d" + tmpdepfile2=`echo "$object" | sed -e 's/.o$/.d/'` + if test "$libtool" = yes; then + "$@" -Wc,-MD + else + "$@" -MD + fi + + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" + exit $stat + fi + + if test -f "$tmpdepfile1"; then + tmpdepfile="$tmpdepfile1" + else + tmpdepfile="$tmpdepfile2" + fi + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" + # That's a space and a tab in the []. + sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" + else + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +#nosideeffect) + # This comment above is used by automake to tell side-effect + # dependency tracking mechanisms from slower ones. + +dashmstdout) + # Important note: in order to support this mode, a compiler *must* + # always write the proprocessed file to stdout, regardless of -o, + # because we must use -o when running libtool. + test -z "$dashmflag" && dashmflag=-M + ( IFS=" " + case " $* " in + *" --mode=compile "*) # this is libtool, let us make it quiet + for arg + do # cycle over the arguments + case "$arg" in + "--mode=compile") + # insert --quiet before "--mode=compile" + set fnord "$@" --quiet + shift # fnord + ;; + esac + set fnord "$@" "$arg" + shift # fnord + shift # "$arg" + done + ;; + esac + "$@" $dashmflag | sed 's:^[^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" + ) & + proc=$! + "$@" + stat=$? + wait "$proc" + if test "$stat" != 0; then exit $stat; fi + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + tr ' ' ' +' < "$tmpdepfile" | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +dashXmstdout) + # This case only exists to satisfy depend.m4. It is never actually + # run, as this mode is specially recognized in the preamble. + exit 1 + ;; + +makedepend) + # X makedepend + ( + shift + cleared=no + for arg in "$@"; do + case $cleared in no) + set ""; shift + cleared=yes + esac + case "$arg" in + -D*|-I*) + set fnord "$@" "$arg"; shift;; + -*) + ;; + *) + set fnord "$@" "$arg"; shift;; + esac + done + obj_suffix="`echo $object | sed 's/^.*\././'`" + touch "$tmpdepfile" + ${MAKEDEPEND-makedepend} 2>/dev/null -o"$obj_suffix" -f"$tmpdepfile" "$@" + ) & + proc=$! + "$@" + stat=$? + wait "$proc" + if test "$stat" != 0; then exit $stat; fi + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + tail +3 "$tmpdepfile" | tr ' ' ' +' | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" "$tmpdepfile".bak + ;; + +cpp) + # Important note: in order to support this mode, a compiler *must* + # always write the proprocessed file to stdout, regardless of -o, + # because we must use -o when running libtool. + ( IFS=" " + case " $* " in + *" --mode=compile "*) + for arg + do # cycle over the arguments + case $arg in + "--mode=compile") + # insert --quiet before "--mode=compile" + set fnord "$@" --quiet + shift # fnord + ;; + esac + set fnord "$@" "$arg" + shift # fnord + shift # "$arg" + done + ;; + esac + "$@" -E | + sed -n '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | + sed '$ s: \\$::' > "$tmpdepfile" + ) & + proc=$! + "$@" + stat=$? + wait "$proc" + if test "$stat" != 0; then exit $stat; fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + cat < "$tmpdepfile" >> "$depfile" + sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvisualcpp) + # Important note: in order to support this mode, a compiler *must* + # always write the proprocessed file to stdout, regardless of -o, + # because we must use -o when running libtool. + ( IFS=" " + case " $* " in + *" --mode=compile "*) + for arg + do # cycle over the arguments + case $arg in + "--mode=compile") + # insert --quiet before "--mode=compile" + set fnord "$@" --quiet + shift # fnord + ;; + esac + set fnord "$@" "$arg" + shift # fnord + shift # "$arg" + done + ;; + esac + "$@" -E | + sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile" + ) & + proc=$! + "$@" + stat=$? + wait "$proc" + if test "$stat" != 0; then exit $stat; fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" + echo " " >> "$depfile" + . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +none) + exec "$@" + ;; + +*) + echo "Unknown depmode $depmode" 1>&2 + exit 1 + ;; +esac + +exit 0 diff --git a/getname.c b/getname.c new file mode 100644 index 0000000..68bdc2f --- /dev/null +++ b/getname.c @@ -0,0 +1,357 @@ + +/* + * This code was taken from hypermail http://www.hypermail.org/ + * + * license: GNU GENERAL PUBLIC LICENSE, Version 2 + * + * modified by Jaakko Heinonen + */ + +#include +#include +#include +/*#include "hypermail.h"*/ +#include "getname.h" +/*#include "setup.h"*/ + +/*extern char *set_domainaddr;*/ +const char *set_domainaddr = ""; +const int use_domainaddr = 0; + +#define NAMESTRLEN 80 +#define MAILSTRLEN 80 + +#define NONAME "(no name)" +#define NOEMAIL "(no email)" + +#ifndef FALSE +# define FALSE 0 +#endif + +#ifndef TRUE +# define TRUE 1 +#endif + +#define hm_strchr(X, XX) strchr(X, XX) +#define strsav(X) ((X == NULL) ? strdup("") : strdup(X)) + +/*const int set_iso2022jp = 0;*/ + +void strcpymax(char *dest, const char *src, int n) +{ + int i; + + if (n) { + n--; /* decrease one to allow for the termination byte */ + for (i = 0; *src && (i < n); i++) + *dest++ = *src++; + } + *dest = 0; +} + +static int blankstring(char *str) +{ + register char *cp; + for (cp = str; *cp; cp++) { + if (*cp != ' ' && *cp != '\t' && *cp != '\r' && *cp != '\n') + return (0); + } + return (1); +} + +#if 0 +char *spamify(char *input) +{ + /* we should replace the @-letter in the email + address */ + int newlen=strlen(input)+4; + char *atptr=strchr(input, '@'); + if(atptr) { + char *newbuf = malloc(newlen); + int index=atptr-input; + /* copy the part before the @ */ + memcpy(newbuf, input, index); + /* append _at_ */ + memcpy(newbuf+index, "_at_", 4); + /* append the part after the @ */ + strcpy(newbuf+index+4, input+index+1); + /* correct the pointer and free the old */ + free(input); + return newbuf; + } + /* weird email, bail out */ + return input; +} +#endif + +/* +** Grabs the name and email address from a From: header. +** This could get tricky; I've tried to keep it simple. +** Should be able to handle all the addresses below: +** +** From: user [no @] +** From: kent (Kent Landfield) [no @ - with comment] +** From: [no text name, use email as text name] +** From: Kent Landfield [text name but no @] +** From: (kent) [comment - no email address] +** From: "" [email address but null comment] +** From: [blank From: line] +** From: uu.net!kent [uucp addresses - no comment] +** From: uu.net!kent (kent) [uucp addresses - with comment] +** From: "(Joe Bloggs)" +** From: "Roy T. Fielding" +** From: kent@localhost +** From: kent@uu.net (Kent Landfield) +** From: (George Burgyan) +** From: (George Burgyan) +** From: Kent B. Landfield +** From: IN%"fekete+reply@c2.net" 26-JAN-1997 13:28:55.36 +** From: IN%"vicric@panix.com" "Vicki Richman" 13-AUG-1996 10:54:33.38 +** From: US2RMC::"lwv26@cas.org" "Larry W. Virden, x2487" 22-OCT-1994 09:44:21.44 +** From: Mail Delivery Subsystem +** From: Self +** From: adam@eden.apana.org.au (Adam Frey) +** From: faqserv@penguin-lust.mit.edu +** From: nc0548@freebsd.netcom.com (Mark Hittinger) +** From: "- Pam Greene, one of the *.answers moderators" +** From: "Felan shena Thoron'edras" +** From: David Muir Sharnoff +** From: A.J.Doherty@reading.ac.uk (Andy Doherty) +** From: Jordan Hubbard +** From: ZXPAN%SLACVM.BITNET@MITVMA.MIT.EDU +** From: afs!piz!alf@uu5.psi.com (Alf the Poet) +** From: answers@cp.tn.tudelft.nl ("Moderator *.answers") +** From: mdw%merengue@merengue.oit.unc.edu (Matt Welsh) +** From: bgoffe@whale.st.usm.edu (William L. Goffe) +** +** This is an interesting new one (1998-11-26): +** From: ›Name.Hidden@era.ericsson.seœ +*/ + +void getname(char *line, char **namep, char **emailp) +{ + int i; + int len; + char *c; + int comment_fnd; + + char email[MAILSTRLEN]; + char name[NAMESTRLEN]; + + len = MAILSTRLEN - 1; + comment_fnd = 0; + + /* + * Zero out data storage. + */ + memset(email, 0, MAILSTRLEN); + memset(name, 0, NAMESTRLEN); + + *namep = NULL; + *emailp = NULL; + + /* EMail Processing First: + ** First, is there an '@' sign we can use as an anchor ? + */ + if ((c = hm_strchr(line, '@')) == NULL) { + /* + ** No '@' sign here so ... + */ + if (strchr(line, '(')) { /* From: bob (The Big Guy) */ + c = strchr(line, ':') + 1; + while (*c == ' ' || *c == '\t') + c++; + for (i = 0; *c && *c != '(' && *c != ' ' && + *c != '\t' && *c != '\n' && i < len; c++) + email[i++] = *c; + email[i] = '\0'; + } + else if ((c = strchr(line, '<'))) { /* From: */ + c++; + for (i = 0; *c && *c != '>' && *c != ' ' && + *c != '\t' && *c != '\n' && i < len; c++) + email[i++] = *c; + email[i] = '\0'; + } + else { + /* + * - check to see if the From: line is blank, (taken care of) + * - check if From: uu.net!kent formatted line + * - check if "From: kent" formatted line + */ + c = strchr(line, ':') + 1; + while (*c == ' ' || *c == '\t') + c++; + for (i = 0; *c && *c != ' ' && *c != '\t' && + *c != '\n' && *c != ',' && i < len; c++) + email[i++] = *c; + email[i] = '\0'; + + } + + if (email[0] == '\0') /* Was it a junk From line ? */ + strcpymax(email, NOEMAIL, MAILSTRLEN); + + else if (use_domainaddr) { + /* + * check if site domainizes addresses + * but don't modify uucp addresses + */ + if ((c = strchr(email, '!')) == NULL) { + strcat(email, "@"); + strcat(email, set_domainaddr); + } + } + } + else { + while (*c != ' ' && *c != '\t' && *c != '<' && *c != '"' && + *c != ':') c--; + c++; + for (i = 0; *c && *c != '>' && *c != ' ' && *c != '\t' && + *c != '"' && *c != '\n' && *c != ']' && *c != ',' && + i < len; c++) + email[i++] = *c; + email[i] = '\0'; + } + + /* + * NAME Processing - Boy are there a bunch of funky formats here. + * No promises... I'll do my best. Let me know + * what I missed... + */ + + if (strchr(line, '<')) { + c = strchr(line, ':') + 1; + while (*c == ' ' || *c == '\t') + c++; + + /* if a comment then just look for the end point */ + + if (*c == '\"') { + int rmparen = 0; + + ++c; + if (*c == '(') { + ++c; + rmparen = 1; + } + for (i = 0, len = NAMESTRLEN - 1; + *c && *c != '\"' && *c != '\n' && i < len; c++) + name[i++] = *c; + + if (rmparen && name[(i - 1)] == ')') + --i; /* get rid of "(name-comment)" parens */ + + comment_fnd = 1; + } + else if (hm_strchr(line, '(')) { + c = hm_strchr(line, '(') + 1; + if (*c == '"') /* is there a comment in the comment ? */ + c++; + } + else if (*c == '<') { /* Comment may be on the end */ + /* From: Bill Campbell */ + c = strchr(line, '>') + 1; + for (i = 0, len = NAMESTRLEN - 1; *c && *c != '\n' && i < len; + c++) + name[i++] = *c; + + comment_fnd = 1; + } + } + else if (strchr(line, '(')) { + c = strchr(line, '('); + c++; + if (*c == '"') /* is there a comment in the comment ? */ + c++; + while (*c == ' ' || *c == '\t') + c++; + } + else if (strchr(line, '[')) { + c = strchr(line, ':') + 1; + while (*c == ' ' || *c == '\t') + c++; + + for (i = 0, len = NAMESTRLEN - 1; + *c && *c != '\"' && *c != '[' && *c != '\n' && i < len; c++) + name[i++] = *c; + + name[--i] = '\0'; + comment_fnd = 1; + } + else { + /* + * Is there an email address available + * that we can use for the name ? + */ + if (!strcmp(email, NOEMAIL)) /* No */ + strcpymax(name, NONAME, NAMESTRLEN); + else { + c = email + strlen(email) - 1; + while (isspace(*c)) + *c-- = '\0'; + strcpymax(name, email, NAMESTRLEN); /* Yes */ + } + *namep = strsav(name); + *emailp = strsav(email); + return; + } + + if (!comment_fnd) { + /*int in_ascii = TRUE, esclen = 0;*/ + for (i = 0, len = NAMESTRLEN - 1; + *c && *c != '<' && *c != '\"' && *c != ')' && *c != '(' && + *c != '\n' && i < len; c++) + { + /*if (set_iso2022jp) { + iso2022_state(c, &in_ascii, &esclen); + if (esclen) { + for (; esclen; esclen--, c++) name[i++] = *c; + for (; in_ascii == FALSE && i < len; + c++, iso2022_state(c, &in_ascii, &esclen)) { + name[i++] = *c; + } + c--; + } else { + name[i++] = *c; + } + } else {*/ + name[i++] = *c; + /*}*/ + } + } + + if (i > 0 && name[i-1] == ' ' && (*c == '<' || *c == '(')) + name[--i] = '\0'; + else + name[i] = '\0'; + + /* + * Is the name string blank ? If so then + * force it to get filled with something. + */ + if (blankstring(name)) + name[0] = '\0'; + + /* Bailing and taking the easy way out... */ + + if (name[0] == '\0') { + if (email[0] == '\0') + strcpymax(name, NONAME, NAMESTRLEN); + else + strcpymax(name, email, NAMESTRLEN); + } + + /* + * need to strip spaces off the end of + * the email and name strings + */ + + c = email + (strlen(email) - 1); + while (c > email && isspace(*c)) + *c-- = '\0'; + + *namep = strsav(name); + *emailp = strsav(email); +} + diff --git a/getname.h b/getname.h new file mode 100644 index 0000000..283a67a --- /dev/null +++ b/getname.h @@ -0,0 +1,9 @@ +#ifndef _GETNAME_H +#define _GETNAME_H + +void getname(char *, char **, char **); +#if 0 +char *spamify(char *input); +#endif + +#endif -- 2.39.2