Added initial LBreakout2 sources, already slightly modified - it does not work yet!

This commit is contained in:
pelya
2010-09-16 15:53:05 +03:00
parent ab7f63b305
commit 3e3025abcc
607 changed files with 192118 additions and 0 deletions

View File

@@ -0,0 +1,8 @@
DEFS = @DEFS@ @network_flag@ @netdebug_flag@ @sdlnet_flag@
noinst_LIBRARIES = libcommon.a
libcommon_a_SOURCES = \
list.c net.c tools.c parser.c
EXTRA_DIST = list.h net.h messages.h tools.h parser.h gettext.h

View File

@@ -0,0 +1,459 @@
# Makefile.in generated by automake 1.9.6 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# 2003, 2004, 2005 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ..
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
INSTALL = @INSTALL@
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
target_triplet = @target@
subdir = common
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/codeset.m4 \
$(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/glibc21.m4 \
$(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intdiv0.m4 \
$(top_srcdir)/m4/intmax.m4 $(top_srcdir)/m4/inttypes-pri.m4 \
$(top_srcdir)/m4/inttypes.m4 $(top_srcdir)/m4/inttypes_h.m4 \
$(top_srcdir)/m4/isc-posix.m4 $(top_srcdir)/m4/lcmessage.m4 \
$(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
$(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/longdouble.m4 \
$(top_srcdir)/m4/longlong.m4 $(top_srcdir)/m4/nls.m4 \
$(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/printf-posix.m4 \
$(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/signed.m4 \
$(top_srcdir)/m4/size_max.m4 $(top_srcdir)/m4/stdint_h.m4 \
$(top_srcdir)/m4/uintmax_t.m4 $(top_srcdir)/m4/ulonglong.m4 \
$(top_srcdir)/m4/wchar_t.m4 $(top_srcdir)/m4/wint_t.m4 \
$(top_srcdir)/m4/xsize.m4 $(top_srcdir)/acinclude.m4 \
$(top_srcdir)/configure.in
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
LIBRARIES = $(noinst_LIBRARIES)
AR = ar
ARFLAGS = cru
libcommon_a_AR = $(AR) $(ARFLAGS)
libcommon_a_LIBADD =
am_libcommon_a_OBJECTS = list.$(OBJEXT) net.$(OBJEXT) tools.$(OBJEXT) \
parser.$(OBJEXT)
libcommon_a_OBJECTS = $(am_libcommon_a_OBJECTS)
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
SOURCES = $(libcommon_a_SOURCES)
DIST_SOURCES = $(libcommon_a_SOURCES)
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
ALLOCA = @ALLOCA@
AMDEP_FALSE = @AMDEP_FALSE@
AMDEP_TRUE = @AMDEP_TRUE@
AMTAR = @AMTAR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@
CATOBJEXT = @CATOBJEXT@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DATADIRNAME = @DATADIRNAME@
DEFS = @DEFS@ @network_flag@ @netdebug_flag@ @sdlnet_flag@
DEPDIR = @DEPDIR@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
GENCAT = @GENCAT@
GLIBC21 = @GLIBC21@
GMSGFMT = @GMSGFMT@
GREP = @GREP@
HAVE_ASPRINTF = @HAVE_ASPRINTF@
HAVE_POSIX_PRINTF = @HAVE_POSIX_PRINTF@
HAVE_SNPRINTF = @HAVE_SNPRINTF@
HAVE_WPRINTF = @HAVE_WPRINTF@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
INSTOBJEXT = @INSTOBJEXT@
INTLBISON = @INTLBISON@
INTLLIBS = @INTLLIBS@
INTLOBJS = @INTLOBJS@
INTL_LIBTOOL_SUFFIX_PREFIX = @INTL_LIBTOOL_SUFFIX_PREFIX@
LDFLAGS = @LDFLAGS@
LIBICONV = @LIBICONV@
LIBINTL = @LIBINTL@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LTLIBICONV = @LTLIBICONV@
LTLIBINTL = @LTLIBINTL@
LTLIBOBJS = @LTLIBOBJS@
MAKEINFO = @MAKEINFO@
MKINSTALLDIRS = @MKINSTALLDIRS@
MSGFMT = @MSGFMT@
MSGMERGE = @MSGMERGE@
OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
POSUB = @POSUB@
RANLIB = @RANLIB@
SDL_CFLAGS = @SDL_CFLAGS@
SDL_CONFIG = @SDL_CONFIG@
SDL_LIBS = @SDL_LIBS@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@
USE_NLS = @USE_NLS@
VERSION = @VERSION@
XGETTEXT = @XGETTEXT@
ac_ct_CC = @ac_ct_CC@
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
appname = @appname@
arch_flag = @arch_flag@
audio_flag = @audio_flag@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
datadir = @datadir@
datarootdir = @datarootdir@
doc_dir = @doc_dir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
hi_dir = @hi_dir@
hi_inst_flag = @hi_inst_flag@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
inst_dir = @inst_dir@
inst_flag = @inst_flag@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
locdir_flag = @locdir_flag@
mandir = @mandir@
mixer_flag = @mixer_flag@
mkdir_p = @mkdir_p@
netdebug_flag = @netdebug_flag@
network_flag = @network_flag@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
sbindir = @sbindir@
sdlnet_flag = @sdlnet_flag@
sdlnet_lib_flag = @sdlnet_lib_flag@
sharedstatedir = @sharedstatedir@
sysconfdir = @sysconfdir@
target = @target@
target_alias = @target_alias@
target_cpu = @target_cpu@
target_os = @target_os@
target_vendor = @target_vendor@
warp_flag = @warp_flag@
win32_deps = @win32_deps@
win32_inst_script = @win32_inst_script@
noinst_LIBRARIES = libcommon.a
libcommon_a_SOURCES = \
list.c net.c tools.c parser.c
EXTRA_DIST = list.h net.h messages.h tools.h parser.h gettext.h
all: all-am
.SUFFIXES:
.SUFFIXES: .c .o .obj
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
&& exit 0; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign common/Makefile'; \
cd $(top_srcdir) && \
$(AUTOMAKE) --foreign common/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
clean-noinstLIBRARIES:
-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
libcommon.a: $(libcommon_a_OBJECTS) $(libcommon_a_DEPENDENCIES)
-rm -f libcommon.a
$(libcommon_a_AR) libcommon.a $(libcommon_a_OBJECTS) $(libcommon_a_LIBADD)
$(RANLIB) libcommon.a
mostlyclean-compile:
-rm -f *.$(OBJEXT)
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/list.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/net.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parser.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tools.Po@am__quote@
.c.o:
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c $<
.c.obj:
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
uninstall-info-am:
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
mkid -fID $$unique
tags: TAGS
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$tags $$unique; \
fi
ctags: CTAGS
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(CTAGS_ARGS)$$tags$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$tags $$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& cd $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) $$here
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
list='$(DISTFILES)'; for file in $$list; do \
case $$file in \
$(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
$(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
esac; \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
dir="/$$dir"; \
$(mkdir_p) "$(distdir)$$dir"; \
else \
dir=''; \
fi; \
if test -d $$d/$$file; then \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
fi; \
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
else \
test -f $(distdir)/$$file \
|| cp -p $$d/$$file $(distdir)/$$file \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile $(LIBRARIES)
installdirs:
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
dvi: dvi-am
dvi-am:
html: html-am
info: info-am
info-am:
install-data-am:
install-exec-am:
install-info: install-info-am
install-man:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-compile mostlyclean-generic
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am: uninstall-info-am
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
clean-noinstLIBRARIES ctags distclean distclean-compile \
distclean-generic distclean-tags distdir dvi dvi-am html \
html-am info info-am install install-am install-data \
install-data-am install-exec install-exec-am install-info \
install-info-am install-man install-strip installcheck \
installcheck-am installdirs maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-compile \
mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
uninstall-am uninstall-info-am
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

View File

@@ -0,0 +1,69 @@
/* Convenience header for conditional use of GNU <libintl.h>.
Copyright (C) 1995-1998, 2000-2002 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU Library 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
Library General Public License for more details.
You should have received a copy of the GNU Library 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. */
#ifndef _LIBGETTEXT_H
#define _LIBGETTEXT_H 1
/* NLS can be disabled through the configure --disable-nls option. */
#if ENABLE_NLS
/* Get declarations of GNU message catalog functions. */
# include <libintl.h>
#else
/* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which
chokes if dcgettext is defined as a macro. So include it now, to make
later inclusions of <locale.h> a NOP. We don't include <libintl.h>
as well because people using "gettext.h" will not include <libintl.h>,
and also including <libintl.h> would fail on SunOS 4, whereas <locale.h>
is OK. */
#if defined(__sun)
# include <locale.h>
#endif
/* Disabled NLS.
The casts to 'const char *' serve the purpose of producing warnings
for invalid uses of the value returned from these functions.
On pre-ANSI systems without 'const', the config.h file is supposed to
contain "#define const". */
# define gettext(Msgid) ((const char *) (Msgid))
# define dgettext(Domainname, Msgid) ((const char *) (Msgid))
# define dcgettext(Domainname, Msgid, Category) ((const char *) (Msgid))
# define ngettext(Msgid1, Msgid2, N) \
((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
# define dngettext(Domainname, Msgid1, Msgid2, N) \
((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \
((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
# define textdomain(Domainname) ((const char *) (Domainname))
# define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname))
# define bind_textdomain_codeset(Domainname, Codeset) ((const char *) (Codeset))
#endif
/* A pseudo function call that serves as a marker for the automated
extraction of messages, but does not call gettext(). The run-time
translation is done at a different place in the code.
The argument, String, should be a literal string. Concatenated strings
and other string expressions won't work.
The macro's expansion is not parenthesized, so that it is suitable as
initializer for static 'char[]' or 'const char[]' variables. */
#define gettext_noop(String) String
#endif /* _LIBGETTEXT_H */

Binary file not shown.

View File

@@ -0,0 +1,360 @@
/***************************************************************************
list.c - description
-------------------
begin : Sun Sep 2 2001
copyright : (C) 2001 by Michael Speck
email : kulkanie@gmx.net
***************************************************************************/
/***************************************************************************
* *
* 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 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include <stdlib.h>
#include "list.h"
/*
====================================================================
Create a new list
auto_delete: Free memory of data pointer when deleting entry
callback: Use this callback to free memory of data including
the data pointer itself.
Return Value: List pointer
====================================================================
*/
List *list_create( int auto_delete, void (*callback)(void*) )
{
List *list = calloc( 1, sizeof( List ) );
list->head = calloc( 1, sizeof( ListEntry ) );
list->tail = calloc( 1, sizeof( ListEntry ) );
list->head->next = list->tail;
list->head->prev = list->head;
list->tail->next = list->tail;
list->tail->prev = list->head;
list->auto_delete = auto_delete;
list->callback = callback;
list->cur_entry = list->head;
return list;
}
/*
====================================================================
Delete list and entries.
====================================================================
*/
void list_delete( List *list )
{
list_clear( list );
free( list->head );
free( list->tail );
free( list );
}
/*
====================================================================
Delete all entries but keep the list. Reset current_entry to head
pointer.
====================================================================
*/
void list_clear( List *list )
{
while( !list_empty( list ) ) list_delete_pos( list, 0 );
}
/*
====================================================================
Insert new item at position.
Return Value: True if successful else False.
====================================================================
*/
int list_insert( List *list, void *item, int pos )
{
int i;
ListEntry *cur = list->head;
ListEntry *new_entry = 0;
/* check if insertion possible */
if ( pos < 0 || pos > list->count ) return 0;
if ( item == 0 ) return 0;
/* get to previous entry */
for (i = 0; i < pos; i++) cur = cur->next;
/* create and anchor new entry */
new_entry = calloc( 1, sizeof( ListEntry ) );
new_entry->item = item;
new_entry->next = cur->next;
new_entry->prev = cur;
cur->next->prev = new_entry;
cur->next = new_entry;
list->count++;
return 1;
}
/*
====================================================================
Add new item at the end of the list.
====================================================================
*/
int list_add( List *list, void *item )
{
ListEntry *new_entry = 0;
/* check if insertion possible */
if ( item == 0 ) return 0;
/* create and anchor new entry */
new_entry = calloc( 1, sizeof( ListEntry ) );
new_entry->item = item;
new_entry->next = list->tail;
new_entry->prev = list->tail->prev;
list->tail->prev->next = new_entry;
list->tail->prev = new_entry;
list->count++;
return 1;
}
/*
====================================================================
Delete item at position. If this was the current entry update
current_entry to valid previous pointer.
Return Value: True if successful else False.
====================================================================
*/
int list_delete_pos( List *list, int pos )
{
int i;
ListEntry *cur = list->head;
/* check if deletion possbile */
if ( list_empty( list ) ) return 0;
if ( pos < 0 || pos >= list->count ) return 0;
/* get to correct entry */
for ( i = 0; i <= pos; i++ ) cur = cur->next;
/* modify anchors */
cur->next->prev = cur->prev;
cur->prev->next = cur->next;
/* decrease counter */
list->count--;
/* check current_entry */
if ( list->cur_entry == cur )
list->cur_entry = list->cur_entry->prev;
/* free memory */
if ( list->auto_delete ) {
if ( list->callback )
(list->callback)( cur->item );
else
free( cur->item );
}
free( cur );
return 1;
}
/*
====================================================================
Delete item if in list. If this was the current entry update
current_entry to valid previous pointer.
Return Value: True if successful else False.
====================================================================
*/
int list_delete_item( List *list, void *item )
{
return list_delete_pos( list, list_check( list, item ) );
}
/*
====================================================================
Delete entry.
Return Value: True if successful else False.
====================================================================
*/
int list_delete_entry( List *list, ListEntry *entry )
{
/* delete possible? */
if ( entry == 0 ) return 0;
if ( list->count == 0 ) return 0;
if ( entry == list->head || entry == list->tail ) return 0;
/* adjust anchor and counter */
entry->prev->next = entry->next;
entry->next->prev = entry->prev;
list->count--;
/* check current_entry */
if ( list->cur_entry == entry )
list->cur_entry = list->cur_entry->prev;
/* free memory */
if ( list->auto_delete ) {
if ( list->callback )
(list->callback)( entry->item );
else
free( entry->item );
}
free( entry );
return 1;
}
/*
====================================================================
Get item from position if in list.
Return Value: Item pointer if found else Null pointer.
====================================================================
*/
void* list_get( List *list, int pos )
{
int i;
ListEntry *cur = list->head;
if ( pos < 0 || pos >= list->count ) return 0;
for ( i = 0; i <= pos; i++ ) cur = cur->next;
return cur->item;
}
/*
====================================================================
Check if item's in list.
Return Value: Position of item else -1.
====================================================================
*/
int list_check( List *list, void *item )
{
int pos = -1;
ListEntry *cur = list->head->next;
while ( cur != list->tail ) {
pos++;
if ( cur->item == item ) break;
cur = cur->next;
}
if ( cur == list->tail ) pos = -1; /* item not found */
return pos;
}
/*
====================================================================
Return first item stored in list and set current_entry to this
entry.
Return Value: Item pointer if found else Null pointer.
====================================================================
*/
void* list_first( List *list )
{
list->cur_entry = list->head->next;
return list->head->next->item;
}
/*
====================================================================
Return last item stored in list and set current_entry to this
entry.
Return Value: Item pointer if found else Null pointer.
====================================================================
*/
void* list_last( List *list )
{
list->cur_entry = list->tail->prev;
return list->tail->prev->item;
}
/*
====================================================================
Return item in current_entry.
Return Value: Item pointer if found else Null pointer.
====================================================================
*/
void* list_current( List *list )
{
return list->cur_entry->item;
}
/*
====================================================================
Reset current_entry to head of list.
====================================================================
*/
void list_reset( List *list )
{
list->cur_entry = list->head;
}
/*
====================================================================
Get next item and update current_entry (reset if tail reached)
Return Value: Item pointer if found else Null (if tail of list).
====================================================================
*/
void* list_next( List *list )
{
list->cur_entry = list->cur_entry->next;
if ( list->cur_entry == list->tail ) list_reset( list );
return list->cur_entry->item;
}
/*
====================================================================
Get previous item and update current_entry.
Return Value: Item pointer if found else Null (if head of list).
====================================================================
*/
void* list_prev( List *list )
{
list->cur_entry = list->cur_entry->prev;
return list->cur_entry->item;
}
/*
====================================================================
Delete the current entry if not tail or head. This is the entry
that contains the last returned item by list_next/prev().
Return Value: True if it was a valid deleteable entry.
====================================================================
*/
int list_delete_current( List *list )
{
if ( list->cur_entry == 0 || list->cur_entry == list->head || list->cur_entry == list->tail ) return 0;
list_delete_entry( list, list->cur_entry );
return 1;
}
/*
====================================================================
Check if list is empty.
Return Value: True if list counter is 0 else False.
====================================================================
*/
int list_empty( List *list )
{
return list->count == 0;
}
/*
====================================================================
Return entry containing the passed item.
Return Value: True if entry found else False.
====================================================================
*/
ListEntry *list_entry( List *list, void *item )
{
ListEntry *entry = list->head->next;
while ( entry != list->tail ) {
if ( entry->item == item ) return entry;
entry = entry->next;
}
return 0;
}
/*
====================================================================
Transfer an entry from one list to another list by removing from
'source' and adding to 'dest' thus if source does not contain
the item this is equvalent to list_add( dest, item ).
====================================================================
*/
void list_transfer( List *source, List *dest, void *item )
{
int old_auto_flag;
/* add to destination */
list_add( dest, item );
/* as the pointer is added to dest without changes only the empty
entry must be deleted in source */
old_auto_flag = source->auto_delete;
source->auto_delete = LIST_NO_AUTO_DELETE;
list_delete_item( source, item );
source->auto_delete = old_auto_flag;
}
/*
====================================================================
Deqeue the first list entry. (must not use auto_delete therefore)
====================================================================
*/
void *list_dequeue( List *list )
{
void *item;
if ( list->count > 0 ) {
item = list->head->next->item;
list_delete_pos( list, 0 );
return item;
}
else
return 0;
}

View File

@@ -0,0 +1,202 @@
/***************************************************************************
list.h - description
-------------------
begin : Sun Sep 2 2001
copyright : (C) 2001 by Michael Speck
email : kulkanie@gmx.net
***************************************************************************/
/***************************************************************************
* *
* 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 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef __LIST_H
#define __LIST_H
#ifdef __cplusplus
extern "C" {
#endif
/*
====================================================================
Dynamic list handling data as void pointers.
====================================================================
*/
typedef struct _ListEntry {
struct _ListEntry *next;
struct _ListEntry *prev;
void *item;
} ListEntry;
typedef struct {
int auto_delete;
int count;
ListEntry *head;
ListEntry *tail;
void (*callback)(void*);
ListEntry *cur_entry;
} List;
/*
====================================================================
Create a new list
auto_delete: Free memory of data pointer when deleting entry
callback: Use this callback to free memory of data including
the data pointer itself.
Return Value: List pointer
====================================================================
*/
enum { LIST_NO_AUTO_DELETE = 0, LIST_AUTO_DELETE };
enum { LIST_NO_CALLBACK = 0 };
List *list_create( int auto_delete, void (*callback)(void*) );
/*
====================================================================
Delete list and entries.
====================================================================
*/
void list_delete( List *list );
/*
====================================================================
Delete all entries but keep the list. Reset current_entry to head
pointer.
====================================================================
*/
void list_clear( List *list );
/*
====================================================================
Insert new item at position.
Return Value: True if successful else False.
====================================================================
*/
int list_insert( List *list, void *item, int pos );
/*
====================================================================
Add new item at the end of the list.
====================================================================
*/
int list_add( List *list, void *item );
/*
====================================================================
Delete item at pos. If this was the current entry update
current_entry to valid previous pointer.
Return Value: True if successful else False.
====================================================================
*/
int list_delete_pos( List *list, int pos );
/*
====================================================================
Delete item if in list. If this was the current entry update
current_entry to valid previous pointer.
Return Value: True if successful else False.
====================================================================
*/
int list_delete_item( List *list, void *item );
/*
====================================================================
Delete entry.
====================================================================
*/
int list_delete_entry( List *list, ListEntry *entry );
/*
====================================================================
Get item from position if in list.
Return Value: Item pointer if found else Null pointer.
====================================================================
*/
void* list_get( List *list, int pos );
/*
====================================================================
Check if item's in list.
Return Value: Position of item else -1.
====================================================================
*/
int list_check( List *list, void *item );
/*
====================================================================
Return first item stored in list and set current_entry to this
entry.
Return Value: Item pointer if found else Null pointer.
====================================================================
*/
void* list_first( List *list );
/*
====================================================================
Return last item stored in list and set current_entry to this
entry.
Return Value: Item pointer if found else Null pointer.
====================================================================
*/
void* list_last( List *list );
/*
====================================================================
Return item in current_entry.
Return Value: Item pointer if found else Null pointer.
====================================================================
*/
void* list_current( List *list );
/*
====================================================================
Reset current_entry to head of list.
====================================================================
*/
void list_reset( List *list );
/*
====================================================================
Get next item and update current_entry (reset if tail reached).
Return Value: Item pointer if found else Null (if tail of list).
====================================================================
*/
void* list_next( List *list );
/*
====================================================================
Get previous item and update current_entry.
Return Value: Item pointer if found else Null (if head of list).
====================================================================
*/
void* list_prev( List *list );
/*
====================================================================
Delete the current entry if not tail or head. This is the entry
that contains the last returned item by list_next/prev().
Return Value: True if it was a valid deleteable entry.
====================================================================
*/
int list_delete_current( List *list );
/*
====================================================================
Check if list is empty.
Return Value: True if list counter is 0 else False.
====================================================================
*/
int list_empty( List *list );
/*
====================================================================
Return entry containing the passed item.
Return Value: True if entry found else False.
====================================================================
*/
ListEntry *list_entry( List *list, void *item );
/*
====================================================================
Transfer an entry from one list to another list by removing from
'source' and adding to 'dest' thus if source does not contain
the item this is equvalent to list_add( dest, item ).
====================================================================
*/
void list_transfer( List *source, List *dest, void *item );
/*
====================================================================
Deqeue the first list entry. (must not use auto_delete therefore)
====================================================================
*/
void *list_dequeue( List *list );
#ifdef __cplusplus
};
#endif
#endif

View File

@@ -0,0 +1,273 @@
/***************************************************************************
messages.h - description
-------------------
begin : Mon Oct 21 12:02:57 CEST 2002
copyright : (C) 2001 by Michael Speck
email : kulkanie@gmx.net
***************************************************************************/
/***************************************************************************
* *
* 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 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef __MESSAGES_H
#define __MESSAGES_H
/* protocol of server and client which must be equal */
#define PROTOCOL 4
/* a list of all messages in the game for client or server */
enum {
/* 00 */
MSG_HEARTBEAT = 0,
/* tells the remote one is still alive. can't be checked in another
* way as the connection is not a stream */
/* 01 */
MSG_ERROR,
/* string message
*
* transfer an error message */
/* 02 */
MSG_SERVER_INFO,
/* string message
*
* server message written to chat */
/* 03 */
MSG_CONNECT,
/* int8 protocol
* string username
* string password
*
* password is currently unused. requests login at server */
/* 04 */
MSG_LOGIN_OKAY,
/* int32 user id
* string user name
*
* accept login and tell client its server user id and its name */
/* 05 */
MSG_DISCONNECT,
/* tell server user has disconnect or vice versa */
/* 06 */
MSG_PREPARE_FULL_UPDATE,
/* clear user list and levelset list */
/* 07 */
MSG_ADD_USER,
/* string user name
* int32 user id
*
* add a visible user. */
/* 08 */
MSG_REMOVE_USER,
/* int32 user id
*
* remove user by that id. is used as well to hide a user */
/* 09 */
MSG_UNHIDE,
/* send by user to set hide 0 after a game was finished.
* prevents buffer overflow when game is done but user is
* idle (looking at stats or whatever) */
/* 0a */
MSG_CHANNEL_LIST,
/* int8 count
* string names
* ...
*
* send the list of all default channels */
/* 0b */
MSG_LEVELSET_LIST,
/* int8 count
* string names
* ...
*
* send the list of all available levelsets */
/* 0c */
MSG_CHATTER,
/* string message
*
* broadcast this message to all visible users */
/* 0d */
MSG_WHISPER,
/* user user id
* string message
*
* whisper this message to the user with the user_id which may be
* located in any channel */
/* 0e */
MSG_COMMAND,
/* string command
*
* user has entered a command. the prepended '/' has already been
* removed by the client */
/* 0f */
MSG_OPEN_GAME,
/* int32 challenged_id
* string setname
* int8 diff
* int8 rounds
* int8 frags
* int8 balls
*
* open a game and add the sending user and the user by id 'challenged_id'
* to it. */
/* 10 */
MSG_CHALLENGE,
/* string username
* string setname
* ... as above
*
* inform user that it has been challenged by 'user_id' */
/* 11 */
MSG_ACCEPT_CHALLENGE,
/* accept challenge (does not require additional data as it is sent
* within the game context) */
/* 12 */
MSG_REJECT_CHALLENGE,
/* reject challenge (as above) */
/* 13 */
MSG_CANCEL_GAME,
/* challenger cancells challenge which will kill the game and unhide
* both users (as above) */
/* 14 */
MSG_BUSY,
/* int32 user_id
*
* user cannot react on a request. the 'user_id' is the
* requesting user who gets the busy message */
/* 15 */
MSG_ENTER_CHANNEL,
/* string name
*
* client requests to server to enter this channel */
/* 16 */
MSG_SET_CHANNEL,
/* string name
*
* set the name of the current channel */
/* 17 */
MSG_QUIT_GAME,
/* if send by a player the opponent will be informed
* and then both are returned to the chat channel */
/* 18 */
MSG_LEVEL_DATA,
/* int8 flags
* string title
* string author
* string bricks
* string extras
*
* leveldata 32+252*2 bytes except the first two byte.
* first tells wether the client plays at top or bottom
* and second tells the comm delay of the server */
/* 19 */
MSG_READY,
/* send by client to confirm reception of level or to
* show that its ready */
/* 1a */
MSG_PAUSE,
/* pause game */
/* 1b */
MSG_UNPAUSE,
/* guess what, eh? */
/* 1c */
MSG_PADDLE_STATE,
/* int16 state
*
* position and fire flags of a paddle */
/* 1d */
MSG_BALL_POSITIONS,
/* ???
*
* attached/moving ball positions */
/* 1e */
MSG_SHOT_POSITIONS,
/* ???
*
* moving shot positions */
/* 1f */
MSG_SCORES,
/* int24 paddle bottom
* int24 paddle top
*
* current scores of paddles */
/* 20 */
MSG_BRICK_HITS,
/* ???
*
* brick modifications */
/* 21 */
MSG_NEW_EXTRAS,
/* ???
*
* extras collected by both paddles */
/* 22 */
MSG_ROUND_OVER,
/* int8 winner
*
* id of winner paddle or -1 if draw */
/* 23 */
MSG_LAST_ROUND_OVER,
/* int8 winner
*
* tells client that game is finished */
/* 24 */
MSG_GAME_STATS,
/* statistics
*
* final game stats */
/* 25 */
MSG_ADD_LEVELSET,
/* string setname
*
* add a new levelset to client information */
/* 26 */
MSG_SET_COMM_DELAY
/* int16 delay
*
* delay between communication frames */
};
#endif

View File

@@ -0,0 +1,765 @@
#include "net.h"
#include "../client/lbreakout.h"
#include <SDL.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <time.h>
/* Basic layer for network communication. A single UDP socket
* is bound to a port. Received packages are stored in one
* global buffer.
* Socket addresses are wrapped in a struct called NetAddr to
* which raw data may be sent as unreliable datagrams.
*
* Error/message stream: sys_printf()
*/
int (*sys_printf)(const char *format, ...) = printf;
/* ********** UDP SOCKET ********** */
#ifdef SDL_NET_ENABLED
UDPsocket SDL_socket = 0;
UDPpacket *SDL_packet = 0;
#else
int net_socket = -1;
#endif
NetAddr net_local_addr;
NetAddr net_sender_addr;
char net_buffer[MAX_MSG_SIZE + PACKET_HEADER_SIZE];
int net_buffer_cur_size = 0;
int net_show_drops = 1;
#ifdef NET_DEBUG_MSG
int net_show_packets = 1;
#else
int net_show_packets = 0;
#endif
#ifdef NETWORK_ENABLED
#ifndef SDL_NET_ENABLED
static void sockaddr_to_netaddr( struct sockaddr *sa, NetAddr *addr )
{
struct sockaddr_in *sin;
addr->sa = *sa;
/* if AF_INET get ip */
if ( sa->sa_family == AF_INET ) {
sin = (struct sockaddr_in*)sa;
*(int *)&addr->inet_ip = *(int *)&sin->sin_addr; /* wow */
}
}
static void netaddr_to_sockaddr( NetAddr *addr, struct sockaddr *sa )
{
*sa = addr->sa;
}
/* resolve name but leave port 0 */
static bool resolve_hostname( char *host, struct sockaddr *sa, int *sa_len )
{
struct sockaddr_in *sin;
struct sockaddr_in6 *sin6;
struct hostent *hostlist;
/* resolve the host's address via DNS lookup */
if ( ( hostlist = gethostbyname( host ) ) == 0 ) {
sys_printf( _("unable to resolve %s: %s\n"), host, strerror( errno) );
return 0;
}
/* put host address to sa struct. simply use the first resolved address */
*sa_len = sizeof(*sa);
memset( sa, 0, *sa_len );
switch ( hostlist->h_addrtype ) {
case AF_INET:
sin = (struct sockaddr_in*)sa;
sin->sin_family = AF_INET;
memcpy( &sin->sin_addr, hostlist->h_addr_list[0], hostlist->h_length );
break;
case AF_INET6:
sin6 = (struct sockaddr_in6*)sa;
sin6->sin6_family = AF_INET6;
memcpy( &sin6->sin6_addr, hostlist->h_addr_list[0], hostlist->h_length );
break;
default:
sys_printf( "unable to resolve: address family %i not supported\n",
hostlist->h_addrtype );
return 0;
}
return 1;
}
static void net_get_local_addr( int port )
{
char buf[MAXHOSTNAMELEN];
struct sockaddr_in sa;
int sa_len;
gethostname(buf, MAXHOSTNAMELEN);
buf[MAXHOSTNAMELEN-1] = 0;
resolve_hostname( buf, (struct sockaddr*)&sa, &sa_len ); /* port is missing */
sa.sin_port = htons((short)port);
sockaddr_to_netaddr( (struct sockaddr *)&sa, &net_local_addr );
}
#endif
#endif
/* open UDP socket */
bool net_init( int port )
{
#ifdef NETWORK_ENABLED
#ifdef SDL_NET_ENABLED
if(SDLNet_Init()==-1) {
sys_printf("SDLNet_Init: %s\n", SDLNet_GetError());
return 0;
}
SDL_socket=SDLNet_UDP_Open(port);
if(!SDL_socket) {
sys_printf("SDLNet_UDP_Open: %s\n", SDLNet_GetError());
return 0;
}
SDL_packet = SDLNet_AllocPacket(MAX_MSG_SIZE + PACKET_HEADER_SIZE);
if(SDL_packet==0) {
sys_printf("cannot allocate packet: out of memory\n" );
return 0;
}
/* net_local_addr is unset */
net_local_addr.SDL_address.host = 0;
net_local_addr.SDL_address.port = 0;
return 1;
#else
struct sockaddr_in sa;
int sa_len;
int fcntl_args, i, new_args;
if ( (net_socket = socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0 )
sys_printf( "couldn't create socket: %s\n", strerror(errno) );
else
if ( fcntl( net_socket, F_GETFL, &fcntl_args) < 0 )
sys_printf( "couldn't get fcntl args: %s\n", strerror(errno) );
else
{
new_args = O_NONBLOCK;
/* no idea, no idea... fcntl seems to work differently since kernel 2.6
if (fcntl_args&O_APPEND) new_args|=O_APPEND;
if (fcntl_args&O_ASYNC) new_args|=O_ASYNC;
if (fcntl_args&O_DIRECT) new_args|=O_DIRECT;*/
if ( fcntl( net_socket, F_SETFL, new_args ) < 0 )
sys_printf( "couldn't set fcntl args: %s\n", strerror(errno) );
else {
sa_len = sizeof(sa);
memset( &sa, 0, sa_len );
sa.sin_family = AF_INET;
sa.sin_port = htons((short)port);
sa.sin_addr.s_addr = htonl(INADDR_ANY); /* all interfaces */
i = 10; /* try ten successive ports */
while ( bind( net_socket, (struct sockaddr*)&sa, sa_len ) < 0 ) {
sys_printf( "binding to port %i failed: %s\n", port, strerror(errno) );
sa.sin_port = htons((short)port++);
if ( --i == 0 ) {
close( net_socket );
return 0;
}
}
net_get_local_addr( port );
sys_printf( _("UDP socket bound to %s:%i\n"),
net_addr_to_string( &net_local_addr ), port );
return 1;
}
}
return 0;
#endif
#else
return 0;
#endif
}
void net_shutdown( void )
{
#ifdef NETWORK_ENABLED
#ifdef SDL_NET_ENABLED
SDLNet_UDP_Close(SDL_socket); SDL_socket = 0;
SDLNet_FreePacket(SDL_packet); SDL_packet = 0;
SDLNet_Quit();
#else
close( net_socket );
sys_printf( "UDP socket closed\n" );
#endif
#endif
}
void net_send_packet( NetAddr *to, int len, void *data )
{
#ifdef NETWORK_ENABLED
#ifdef SDL_NET_ENABLED
SDL_packet->channel = -1;
memcpy( SDL_packet->data, data, len );
SDL_packet->len = len;
SDL_packet->address = to->SDL_address;
SDLNet_UDP_Send(SDL_socket,-1,SDL_packet);
#else
struct sockaddr sa;
/* empty packets are not send */
if ( len == 0 ) {
sys_printf( "net_send_packet: null length packet\n" );
return;
}
netaddr_to_sockaddr( to, &sa );
if ( sendto( net_socket, data, len, 0, &sa, sizeof(sa) ) < 0 ) {
if (errno == EWOULDBLOCK)
return;
if (errno == ECONNREFUSED)
return;
sys_printf( "net_send_packet: %s\n", strerror(errno) );
}
#endif
#endif
}
bool net_recv_packet( void )
{
#ifdef NETWORK_ENABLED
int ret;
#ifdef SDL_NET_ENABLED
ret = SDLNet_UDP_Recv(SDL_socket, SDL_packet);
if ( ret == -1 ) {
sys_printf("SDLNet_UDP_Recv: %s\n", SDLNet_GetError());
return 0;
}
if ( ret == 1 ) {
memcpy( net_buffer, SDL_packet->data, SDL_packet->len );
net_buffer_cur_size = SDL_packet->len;
net_sender_addr.SDL_address = SDL_packet->address;
return 1;
}
net_buffer_cur_size = 0;
return 0;
#else
struct sockaddr sa;
int sa_len = sizeof(sa);
ret = recvfrom( net_socket,
net_buffer, sizeof(net_buffer),
0,
&sa, &sa_len);
if (ret == -1) {
if (errno == EWOULDBLOCK)
return 0;
if (errno == ECONNREFUSED)
return 0;
sys_printf( "net_recv_packet: %s\n", strerror(errno));
return 0;
}
net_buffer_cur_size = ret;
sockaddr_to_netaddr( &sa, &net_sender_addr );
return (ret>0);
#endif
#else
return 0;
#endif
}
/* if host contains trailing :xxxxx 'port' is overwritten */
bool net_build_addr( NetAddr *addr, char *host, int port )
{
#ifdef NETWORK_ENABLED
char *ptr;
#ifndef SDL_NET_ENABLED
struct sockaddr sa;
int sa_len;
#endif
if ( (ptr = strchr( host, ':' )) ) {
*ptr = 0;
port = atoi( ptr+1 );
}
#ifdef SDL_NET_ENABLED
if ( SDLNet_ResolveHost(&addr->SDL_address, host, port ) == -1 )
{
sys_printf("SDLNet_ResolveHost: %s\n", SDLNet_GetError());
return 0;
}
return 1;
#else
memset( addr, 0, sizeof( NetAddr ) );
if ( resolve_hostname( host, &sa, &sa_len ) ) {
switch ( sa.sa_family ) {
case AF_INET:
((struct sockaddr_in*)&sa)->sin_port = htons((short)port);
break;
case AF_INET6:
((struct sockaddr_in6*)&sa)->sin6_port = htons((short)port);
break;
default:
/* not reached as resolve_hostname allows the same types */
return 0;
}
sockaddr_to_netaddr( &sa, addr );
return 1;
}
return 0;
#endif
#else
return 0;
#endif
}
/* compare host and port */
bool net_compare_addr( NetAddr *a1, NetAddr *a2 )
{
#ifdef NETWORK_ENABLED
#ifdef SDL_NET_ENABLED
if ( a1->SDL_address.host == a2->SDL_address.host )
if ( a1->SDL_address.port == a2->SDL_address.port )
return 1;
return 0;
#else
/* by now only AF_INET addresses may be compared */
if ( a1->sa.sa_family == AF_INET && a2->sa.sa_family == AF_INET ) {
if ( a1->inet_ip[0] == a2->inet_ip[0] )
if ( a1->inet_ip[1] == a2->inet_ip[1] )
if ( a1->inet_ip[2] == a2->inet_ip[2] )
if ( a1->inet_ip[3] == a2->inet_ip[3] )
if ( ((struct sockaddr_in*)&a1->sa)->sin_port ==
((struct sockaddr_in*)&a2->sa)->sin_port )
return 1;
return 0;
}
sys_printf( "only AF_INET addresses may be compared yet\n" );
return 0;
#endif
#else
return 0;
#endif
}
char *net_addr_to_string( NetAddr *_addr ) /* not allocated but static */
{
#ifdef NETWORK_ENABLED
#ifdef SDL_NET_ENABLED
int ip[4];
static char host_ip[64];
char *host;
if(!(host=SDLNet_ResolveIP(&_addr->SDL_address)))
{
//printf("SDLNet_ResolveIP: %s\n", SDLNet_GetError());
ip[0] = _addr->SDL_address.host & 0xff;
ip[1] = (_addr->SDL_address.host>>8) & 0xff;
ip[2] = (_addr->SDL_address.host>>16) & 0xff;
ip[3] = (_addr->SDL_address.host>>24) & 0xff;
snprintf( host_ip, 64, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3] );
return host_ip;
}
return host;
#else
static char str[64];
int len = 64;
struct sockaddr *addr = &_addr->sa;
struct sockaddr_in *sin;
struct sockaddr_in6 *sin6;
/*struct sockaddr_un *sun;*/
str[len-1] = 0;
snprintf( str, len, "undefined" );
switch ( addr->sa_family ) {
case AF_INET:
sin = (struct sockaddr_in*)addr;
if ( !inet_ntop( AF_INET, &sin->sin_addr, str, len ) ) {
sys_printf( "inet_ntop failed: %s\n", strerror( errno ) );
}
break;
case AF_INET6:
sin6 = (struct sockaddr_in6*)addr;
if ( !inet_ntop( AF_INET6, &sin6->sin6_addr, str, len ) ) {
sys_printf( "inet_ntop failed: %s\n", strerror( errno ) );
}
break;
case AF_UNIX:
/*sun = (struct sockaddr_un *)addr;
if( sun->sun_path[0] == 0 ) {
snprintf( str, len, "unknown" );
sys_printf( "net_query_ip: unknown unix path\n" );
}
else
snprintf( str, sun->sun_path, len );*/
break;
default:
snprintf( str, len, "unknown" );
break;
}
return str;
#endif
#else
return 0;
#endif
}
/* ********** MESSAGE ********** */
char *msg_buf = 0;
int *msg_buf_cur_size = 0;
int msg_buf_max_size = 0;
int msg_write_overflow = 0;
#ifdef NET_DEBUG_MSG
static void msg_print_raw( int len, char *buf )
{
int i;
for ( i = 0; i < len; i++ )
printf( "%02x ", (unsigned char) buf[i] );
printf( "\n" );
}
#endif
static char* msg_get_writeable_space( int size )
{
if ( *msg_buf_cur_size + size > msg_buf_max_size ) {
msg_write_overflow = 1;
*msg_buf_cur_size = 0;
}
return msg_buf + *msg_buf_cur_size;
}
void msg_begin_writing( char *buf, int *cur_size, int max_size )
{
msg_buf = buf;
msg_buf_cur_size = cur_size;
msg_buf_max_size = max_size;
*msg_buf_cur_size = 0;
msg_write_overflow = 0;
}
void msg_write_int8 ( int c )
{
unsigned char *ptr = msg_get_writeable_space( 1 );
ptr[0] = (char)c;
*msg_buf_cur_size += 1;
}
void msg_write_int16 ( int s )
{
unsigned char *ptr = msg_get_writeable_space( 2 );
ptr[0] = s & 0xff;
ptr[1] = (s>>8) & 0xff;
*msg_buf_cur_size += 2;
}
void msg_write_int32 ( int i )
{
unsigned char *ptr = msg_get_writeable_space( 4 );
ptr[0] = i & 0xff;
ptr[1] = (i>>8) & 0xff;
ptr[2] = (i>>16) & 0xff;
ptr[3] = (i>>24) & 0xff;
*msg_buf_cur_size += 4;
}
void msg_write_string( char *str )
{
char *ptr = msg_get_writeable_space( strlen(str)+1 );
if ( strlen(str)+1 > msg_buf_max_size ) return; /* would cause segfault */
strcpy( ptr, str );
*msg_buf_cur_size += strlen(str)+1;
}
void msg_printf ( char *format, ... )
{
char buf[MAX_MSG_SIZE];
va_list args;
va_start( args, format );
vsnprintf( buf, MAX_MSG_SIZE, format, args ); buf[MAX_MSG_SIZE-1] = 0;
va_end( args );
msg_write_string( buf );
}
void msg_write ( int len, void *data )
{
unsigned char *ptr = msg_get_writeable_space( len );
if ( len > msg_buf_max_size ) return; /* would cause segfault */
memcpy( ptr, data, len );
*msg_buf_cur_size += len;
}
int msg_get_max_size()
{
return msg_buf_max_size;
}
bool msg_write_failed()
{
return msg_write_overflow;
}
int msg_read_exceeded = 0;
int msg_read_pos = 0;
static char* msg_get_readable_space( int size )
{
if ( msg_read_pos + size > net_buffer_cur_size ) {
msg_read_exceeded = 1;
msg_read_pos = 0;
}
return net_buffer + msg_read_pos;
}
bool msg_is_connectionless()
{
return ( *(int*)net_buffer == 0 );
}
void msg_begin_reading()
{
msg_read_exceeded = 0;
msg_read_pos = 0;
}
void msg_begin_connectionless_reading()
{
msg_read_exceeded = 0;
msg_read_pos = PACKET_HEADER_SIZE;
}
int msg_read_int8 ( void )
{
unsigned char *ptr = msg_get_readable_space( 1 );
msg_read_pos += 1;
return ptr[0];
}
int msg_read_int16( void )
{
unsigned char *ptr = msg_get_readable_space( 2 );
msg_read_pos += 2;
return ptr[0] + (ptr[1]<<8);
}
int msg_read_int32( void )
{
unsigned char *ptr = msg_get_readable_space( 4 );
msg_read_pos += 4;
return ptr[0] + (ptr[1]<<8) + (ptr[2]<<16) + (ptr[3]<<24);
}
char* msg_read_string( void )
{
static char buf[MAX_MSG_SIZE]; /* can't be bigger including trailing \0 */
char c;
int i = 0;
while ( 1 ) {
c = msg_read_int8();
buf[i++] = c;
if ( i == MAX_MSG_SIZE ) break; /* to be sure */
if ( c == 0 ) break;
}
buf[MAX_MSG_SIZE-1] = 0;
return buf;
}
void msg_read( int len, char *buf )
{
unsigned char *ptr = msg_get_readable_space( len );
msg_read_pos += len;
memcpy( buf, ptr, len );
}
bool msg_read_failed( void )
{
return msg_read_exceeded;
}
/* ********** TRANSMISSION ********** */
/* transmit a connectionless message */
void net_transmit_connectionless( NetAddr *addr, int len, char *data )
{
int cur_size;
char packet[PACKET_HEADER_SIZE + MAX_MSG_SIZE];
memset( packet, 0, PACKET_HEADER_SIZE ); /* connectionless header */
msg_begin_writing( packet + PACKET_HEADER_SIZE, &cur_size, MAX_MSG_SIZE );
msg_write( len, data );
if ( msg_write_failed() ) return;
net_send_packet( addr, PACKET_HEADER_SIZE + cur_size, packet );
if ( net_show_packets )
sys_printf( "--> %s: connectionless size=%i\n",
net_addr_to_string( addr ),
cur_size + PACKET_HEADER_SIZE );
}
void socket_init( NetSocket *sock, NetAddr *addr )
{
memset( sock, 0, sizeof( NetSocket ) );
sock->remote_addr = *addr;
sock->outgoing_id = 1; /* as id 0 means connectionless */
sock->idle_since = time(0);
//sys_printf( "%s: socket initiated\n", net_addr_to_string( addr ) );
}
void socket_reinit( NetSocket *socket ) /* with same address */
{
NetAddr addr = socket->remote_addr;
socket_init( socket, &addr );
}
void socket_print_stats( NetSocket *sock )
{
sys_printf ( "%s: STATISTICS\n drops: %i(%i packets)\n %i good packets\n",
net_addr_to_string( &sock->remote_addr ),
sock->drop_count, sock->dropped_packet_count,
sock->good_packet_count );
}
/* transmit CODE_RED/BLUE message and re-transmit dropped CODE_RED messages.
* length 0 messages are not transmitted. re-transmission of CODE_RED messages
* is handled in any case */
void socket_transmit( NetSocket *sock, int code, int len, char *data )
{
char packet[PACKET_HEADER_SIZE + MAX_MSG_SIZE];
int is_code_red = 0, cur_size = 0;
/* do not use sockets with fatal error */
if ( sock->fatal_error ) return;
/* add code red message to buffer */
if ( code == CODE_RED ) {
if ( sock->code_red_buf_cur_size + len > MAX_MSG_SIZE ) {
sock->fatal_error = 1; /* overflowed */
return;
}
memcpy( sock->code_red_buf + sock->code_red_buf_cur_size, data, len );
sock->code_red_buf_cur_size += len;
/* do not send the message if waiting for a receipt */
if ( sock->outgoing_code_red > 0 && !sock->retransmit_code_red_buf )
return;
else
is_code_red = 1;
}
if ( sock->retransmit_code_red_buf )
is_code_red = 1;
msg_begin_writing( packet, &cur_size, PACKET_HEADER_SIZE + MAX_MSG_SIZE );
msg_write_int32( sock->outgoing_id | (is_code_red<<31) );
msg_write_int32( sock->incoming_code_red );
if ( is_code_red )
sock->outgoing_code_red = sock->outgoing_id;
sock->outgoing_id++;
/* if code red buffer was not received resend it and clear the flag.
* if not waiting for a receipt (thus an initial code red message)
* send it as well */
if ( is_code_red ) {
msg_write( sock->code_red_buf_cur_size, sock->code_red_buf );
sock->retransmit_code_red_buf = 0;
}
/* add code blue packet if space is left */
if ( code == CODE_BLUE && cur_size + len <= msg_get_max_size() )
msg_write( len, data );
/* no data? */
if ( cur_size == PACKET_HEADER_SIZE ) return;
/* send packet */
net_send_packet( &sock->remote_addr, cur_size, packet );
#ifdef NET_DEBUG_MSG
printf( "OUT: "); msg_print_raw( cur_size, packet );
#endif
if ( net_show_packets )
sys_printf( "--> %s: out=%i(%s) size=%i in=%i(RED:%i)\n",
net_addr_to_string( &sock->remote_addr ),
sock->outgoing_id-1, is_code_red?"RED":"BLUE",
cur_size,
sock->incoming_id, sock->incoming_code_red );
}
/* update socker by net_packet header if net_sender_addr is sock.remote_addr
* and set read pointer to packet payload. if false is returned packet is
* not parsed. */
bool socket_process_header( NetSocket *sock )
{
int id, is_code_red, last_ack_code_red, drops = 0;
/* do not process fatal socks */
if ( sock->fatal_error ) return 0;
/* correct sock? */
if ( !net_compare_addr( &net_sender_addr, &sock->remote_addr ) )
return 0;
#ifdef NET_DEBUG_MSG
printf( " IN: " ); msg_print_raw( net_buffer_cur_size, net_buffer );
#endif
/* read header */
msg_begin_reading();
id = msg_read_int32(); /* new incoming id, the difference to sock->incoming_id is
the number of dropped packets */
is_code_red = id >> 31; /* highest bit tells wether code red packet */
id &= ~(1<<31);
last_ack_code_red = msg_read_int32(); /* last code red packet remote received */
/* duplicated packets are not handled */
if ( id <= sock->incoming_id ) {
if ( net_show_drops )
sys_printf( "%s: out of order packet %i at %i\n",
net_addr_to_string( &sock->remote_addr ),
id, sock->incoming_id );
return 0;
}
/* despite dropped packets this packet is handled */
if ( id > sock->incoming_id+1 ) {
drops = id - (sock->incoming_id+1);
sock->dropped_packet_count += drops;
sock->drop_count++;
if ( net_show_drops )
sys_printf( "%s: dropped %i packets at %i\n",
net_addr_to_string( &sock->remote_addr ),
drops, sock->incoming_id+1 );
}
sock->good_packet_count++;
sock->incoming_id = id; /* last incoming packet (no matter wether red or blue) */
if ( is_code_red )
sock->incoming_code_red = id; /* last code red packet socket received */
if ( sock->outgoing_code_red ) {
if ( sock->outgoing_code_red == last_ack_code_red ) {
/* was received so we can clear code_red buffer */
sock->outgoing_code_red = 0;
sock->code_red_buf_cur_size = 0;
}
else
if ( sock->outgoing_code_red > last_ack_code_red ) {
/* resend code_red buffer as it was dropped */
sock->retransmit_code_red_buf = 1;
}
else {
/* fatal error occured as remote received a newer code red packet
* although we had no receipt for the current one */
sock->fatal_error = 1;
}
}
sock->idle_since = time(0); /* reset idle time stamp */
/* if packet is empty mark it as unreadable */
if ( msg_read_pos == net_buffer_cur_size )
return 0;
return 1;
}

View File

@@ -0,0 +1,121 @@
#ifndef __NET_H
#define __NET_H
#ifdef NETWORK_ENABLED
#ifdef SDL_NET_ENABLED
#include <SDL_net.h>
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/param.h>
#include <sys/time.h>
#include <unistd.h>
#include <fcntl.h>
#include <netinet/tcp.h>
#include <netinet/in.h>
#include <netdb.h>
#include <errno.h>
#include <arpa/inet.h>
#include <sys/poll.h>
#include <signal.h>
#endif
#endif
#ifndef bool
#define bool int
#endif
typedef struct {
#ifdef NETWORK_ENABLED
#ifdef SDL_NET_ENABLED
IPaddress SDL_address;
#else
struct sockaddr sa;
unsigned char inet_ip[4]; /* AF_INET dotted ip */
#endif
#endif
} NetAddr;
#define MAX_MSG_SIZE 1016
#define PACKET_HEADER_SIZE 8
typedef struct {
NetAddr remote_addr;
int fatal_error; /* code red buffer has been flooded */
int idle_since; /* global time stamp when last packet was received (secs) */
int drop_count; /* number of drops */
int dropped_packet_count; /* number of dropped packets */
int good_packet_count; /* number of successfully processed packets */
int incoming_id; /* last incoming remote outgoing_id */
int outgoing_id; /* packet id increased every sent */
int incoming_code_red; /* id of last incoming code red packet. is sent
in the header to let remote know if any code
red packets were dropped */
int outgoing_code_red; /* last outgoing_id of code_red packet if socket
is still waiting for reception acknowledgment. if
packet was delivered successfully this is cleared
to 0 as well as code_red_buf */
int retransmit_code_red_buf; /* retransmit buffer as net_process_header
has received an incoming_code_red less
than outgoing_code_red */
char code_red_buf[MAX_MSG_SIZE];
char code_red_buf_cur_size;
} NetSocket;
extern NetAddr net_local_addr;
extern NetAddr net_sender_addr;
bool net_init( int port );
void net_shutdown( void );
void net_send_packet( NetAddr *to, int len, void *data );
bool net_recv_packet( void ); /* into net_packet from net_sender_addr */
bool net_build_addr( NetAddr *addr, char *host, int port );
bool net_compare_addr( NetAddr *a1, NetAddr *a2 );
char *net_addr_to_string( NetAddr *addr ); /* not allocated but static */
void msg_begin_writing( char *buf, int *cur_size, int max_size );
void msg_write_int8 ( int c );
void msg_write_int16 ( int s );
void msg_write_int32 ( int i );
void msg_write_string( char *str );
void msg_printf ( char *format, ... );
void msg_write ( int len, void *data );
int msg_get_max_size();
bool msg_write_failed(); /* check wether overflow occured */
bool msg_is_connectionless();
void msg_begin_reading(); /* of net_packet, starts at header */
void msg_begin_connectionless_reading(); /* of net_packet, starts after header as useless data */
int msg_read_int8 ( void );
int msg_read_int16( void );
int msg_read_int32( void );
char* msg_read_string( void );
void msg_read( int len, char *buf );
bool msg_read_failed(); /* check wether data couldn't be extracted */
void socket_init( NetSocket *sock, NetAddr *addr );
void socket_reinit( NetSocket *socket ); /* with same address */
void socket_print_stats( NetSocket *sock );
/* transmit a connectionless message */
void net_transmit_connectionless( NetAddr *addr, int len, char *data );
/* transmit CODE_RED/BLUE message and re-transmit dropped CODE_RED messages.
* length 0 messages are not transmitted but re-transmission of CODE_RED messages
* is handled in any case */
#define CODE_BLUE 0
#define CODE_RED 1
void socket_transmit( NetSocket *sock, int code, int len, char *data );
/* update socket by net_packet header if net_sender_addr is socket.remote_addr
* and set read pointer to packet payload. if false is returned packet is
* not parsed. */
bool socket_process_header( NetSocket *sock );
#endif

View File

@@ -0,0 +1,697 @@
/***************************************************************************
parser.c - description
-------------------
begin : Sat Mar 9 2002
copyright : (C) 2001 by Michael Speck
email : kulkanie@gmx.net
***************************************************************************/
/***************************************************************************
* *
* 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 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include <stdlib.h>
#include <string.h>
#include "parser.h"
#include "tools.h"
/*
====================================================================
Error string.
====================================================================
*/
static char parser_sub_error[1024];
static char parser_error[1024];
/*
====================================================================
This buffer is used to fully load resource files when the
compact format is used.
====================================================================
*/
enum { CBUFFER_SIZE = 131072 }; /* 128 KB */
static char cbuffer[CBUFFER_SIZE];
static char* cbuffer_pos = 0; /* position in cbuffer */
/*
====================================================================
As we need constant strings sometimes we have to define a maximum
length for tokens.
====================================================================
*/
enum { PARSER_MAX_TOKEN_LENGTH = 1024 };
/*
====================================================================
Locals
====================================================================
*/
/*
====================================================================
Macro to shorten the fread call for a single character.
====================================================================
*/
#define FILE_READCHAR( file, c ) fread( &c, sizeof( char ), 1, file )
/*
====================================================================
Find next newline in cbuffer and replace it with \0 and return the
pointer to the current line.
====================================================================
*/
static char* parser_get_next_line()
{
char *line = cbuffer_pos;
char *newpos;
if ( cbuffer_pos[0] == 0 )
return 0; /* completely read. no more lines. */
if ( ( newpos = strchr( cbuffer_pos, 10 ) ) == 0 )
cbuffer_pos += strlen( cbuffer_pos ); /* last line */
else {
cbuffer_pos = newpos + 1; /* set pointer to next line */
newpos[0] = 0; /* terminate current line */
}
return line;
}
/*
====================================================================
Set parse error string: "file:line: error"
====================================================================
*/
static void parser_set_parse_error( char *fname, FILE *file, char *error )
{
int end, pos;
int line_count = 1;
char c;
end = ftell( file ); pos = 0;
fseek( file, 0, SEEK_SET );
while ( pos < end ) {
FILE_READCHAR( file, c ); pos++;
if ( c == 10 ) line_count++;
}
sprintf( parser_error, "%s: %i: %s",
fname, line_count, error );
}
/*
====================================================================
Check if the given character occurs in the symbol list.
If the first symbol is ' ' it is used as wildcard for all
white-spaces.
====================================================================
*/
static int is_symbol( int c, char *symbols )
{
int i = 0;
if ( symbols[0] == ' ' && c <= 32 ) return 1;
while ( symbols[i] != 0 )
if ( c == symbols[i++] )
return 1;
return 0;
}
/*
====================================================================
Move file position forward until reading in the given character.
If stop is ' ' whitespaces will be ignored.
====================================================================
*/
static void file_skip( FILE *file, char stop )
{
char c = 0;
FILE_READCHAR( file, c );
while ( ( ( stop == ' ' && c <= 32 ) || ( stop != ' ' && c != stop ) ) && !feof( file ) )
FILE_READCHAR( file, c );
if ( !feof( file ) )
fseek( file, -1, SEEK_CUR );
}
/*
====================================================================
Read next token from current file position where symbols is a
list of characters used to break up the tokens. The symbols
themself are returned as tokens. If ' ' occurs in the symbol list
it will be ignored and whitespaces are removed automatically.
The token does not exceed PARSER_MAX_TOKEN_LENGTH.
Enclosing ".." are kept at the token. Use file_compare_token()
to test it's contents.
Returns False on EoF.
====================================================================
*/
static int file_read_token_intern( FILE *file, char *symbols, char *token )
{
int pos = 0;
char c;
token[0] = 0;
file_skip( file, ' ' );
FILE_READCHAR( file, c );
if ( feof( file ) ) {
sprintf( parser_sub_error, "unexpected end of file" );
return 0;
}
/* string? */
if ( c == '"' ) {
token[pos++] = '"';
FILE_READCHAR( file, c );
while ( ( !feof( file ) && c != '"' ) ) {
token[pos++] = c;
if ( pos == PARSER_MAX_TOKEN_LENGTH - 2 ) {
token[pos++] = '"';
token[pos] = 0;
sprintf( parser_sub_error, "token exceeds limit" );
return 0;
}
FILE_READCHAR( file, c );
}
token[pos++] = '"';
token[pos] = 0;
if ( feof( file ) ) {
sprintf( parser_sub_error, "unexpected end of file" );
token[0] = 0;
return 0;
}
return 1;
}
/* symbol? */
if ( is_symbol( c, symbols ) ) {
token[0] = c; token[1] = 0;
return 1;
}
/* other token */
while ( !is_symbol( c, symbols ) && !feof( file ) ) {
token[pos++] = c;
if ( pos == PARSER_MAX_TOKEN_LENGTH - 1 ) {
token[pos] = 0;
sprintf( parser_sub_error, "token exceeds limit" );
return 0;
}
FILE_READCHAR( file, c );
}
token[pos] = 0;
if ( feof( file ) )
return 1;
fseek( file, -1, SEEK_CUR );
return 1;
}
/*
====================================================================
Skip all tokens until one begins with character 'stop'. This
token is also ignored.
====================================================================
*/
static void file_skip_section( FILE *file, char stop )
{
char token[PARSER_MAX_TOKEN_LENGTH];
do {
file_read_token_intern( file, PARSER_SYMBOLS, token );
} while ( !feof( file ) && token[0] != stop );
}
/*
====================================================================
Read next token and skip comments enclosed in tokens
skip[0], skip[1] (if skip is not NULL).
Return 0 if EoF.
====================================================================
*/
static int file_read_token( FILE *file, char *symbols, char *skip, char *token )
{
while ( 1 ) {
if ( !file_read_token_intern( file, symbols, token ) )
return 0;
if ( skip ) {
if ( token[0] == skip[0] )
file_skip_section( file, skip[1] );
else
break;
}
else
break;
}
return 1;
}
/*
====================================================================
Remove quotes if any and return result as newly allocated string.
====================================================================
*/
static char* parser_remove_quotes( char *string )
{
char *new;
if ( string[0] != '"' )
return strdup( string );
new = calloc( strlen( string ) - 1, sizeof( char ) );
strncpy( new, string + 1, strlen( string ) - 2 );
new[strlen( string ) - 2] = 0;
return new;
}
/*
====================================================================
Proceed in the given string until it ends or non-whitespace occurs
and return the new position.
====================================================================
*/
static char* string_ignore_whitespace( char *string )
{
int i = 0;
while ( string[i] != 0 && string[i] <= 32 ) i++;
return string + i;
}
/*
====================================================================
This function searches file from the current position for the next
pdata entry.
====================================================================
*/
static PData* parser_parse_file( FILE *file )
{
char token[PARSER_MAX_TOKEN_LENGTH];
PData *pd = 0, *sub = 0;
/* get name */
if ( !file_read_token( file, PARSER_SYMBOLS, PARSER_SKIP_SYMBOLS, token ) )
return 0;
if ( is_symbol( token[0], PARSER_SYMBOLS ) ) {
sprintf( parser_sub_error, "parse error before '%s'", token );
return 0;
}
pd = calloc( 1, sizeof( PData ) );
pd->name = parser_remove_quotes( token );
/* check type */
if ( !file_read_token( file, PARSER_SYMBOLS, PARSER_SKIP_SYMBOLS, token ) )
goto failure;
switch ( token[0] ) {
case PARSER_SET:
/* assign single value or list */
pd->values = list_create( LIST_AUTO_DELETE, LIST_NO_CALLBACK );
if ( !file_read_token( file, PARSER_SYMBOLS, PARSER_SKIP_SYMBOLS, token ) )
goto failure;
if ( token[0] != PARSER_LIST_BEGIN ) {
if ( is_symbol( token[0], PARSER_SYMBOLS ) ) {
sprintf( parser_sub_error, "parse error before '%s'", token );
goto failure;
}
else
list_add( pd->values, parser_remove_quotes( token ) );
}
else {
if ( !file_read_token( file, PARSER_SYMBOLS, PARSER_SKIP_SYMBOLS, token ) )
goto failure;
while ( token[0] != PARSER_LIST_END ) {
if ( is_symbol( token[0], PARSER_SYMBOLS ) ) {
sprintf( parser_sub_error, "parse error before '%s'", token );
goto failure;
}
else
list_add( pd->values, parser_remove_quotes( token ) );
if ( !file_read_token( file, PARSER_SYMBOLS, PARSER_SKIP_SYMBOLS, token ) )
goto failure;
}
}
break;
case PARSER_GROUP_BEGIN:
/* check all entries until PARSER_GROUP_END */
pd->entries = list_create( LIST_NO_AUTO_DELETE, LIST_NO_CALLBACK );
while ( 1 ) {
if ( !file_read_token( file, PARSER_SYMBOLS, PARSER_SKIP_SYMBOLS, token ) )
goto failure;
if ( token[0] == PARSER_GROUP_END )
break;
fseek( file, -strlen( token ), SEEK_CUR );
sub = parser_parse_file( file );
if ( sub )
list_add( pd->entries, sub );
else
goto failure;
}
break;
default:
sprintf( parser_sub_error, "parse error before '%s'", token );
goto failure;
}
return pd;
failure:
parser_free( &pd );
return 0;
}
/*
====================================================================
Publics
====================================================================
*/
/*
====================================================================
This function splits a string into tokens using the characters
found in symbols as breakpoints. If the first symbol is ' ' all
whitespaces are used as breakpoints though NOT added as a token
(thus removed from string).
====================================================================
*/
List* parser_split_string( char *string, char *symbols )
{
int pos;
char *token = 0;
List *list = list_create( LIST_AUTO_DELETE, LIST_NO_CALLBACK );
while ( string[0] != 0 ) {
if ( symbols[0] == ' ' )
string = string_ignore_whitespace( string );
if ( string[0] == 0 ) break;
pos = 1; /* 'read in' first character */
while ( string[pos - 1] != 0 && !is_symbol( string[pos - 1], symbols ) && string[pos - 1] != '"' ) pos++;
if ( pos > 1 )
pos--;
else
if ( string[pos - 1] == '"' ) {
/* read a string */
string = string + 1; pos = 0;
while ( string[pos] != 0 && string[pos] != '"' ) pos++;
token = calloc( pos + 1, sizeof( char ) );
strncpy( token, string, pos ); token[pos] = 0;
list_add( list, token );
string = string + pos + (string[pos] != 0);
continue;
}
token = calloc( pos + 1, sizeof( char ) );
strncpy( token, string, pos); token[pos] = 0;
list_add( list, token );
string = string + pos;
}
return list;
}
/*
====================================================================
This is the light version of parser_split_string which checks for
just one character and does not add this glue characters to the
list. It's about 2% faster. Wow.
====================================================================
*/
List *parser_explode_string( char *string, char c )
{
List *list = list_create( LIST_AUTO_DELETE, LIST_NO_CALLBACK );
char *next_slash = 0;
char buffer[64];
while ( string[0] != 0 && ( next_slash = strchr( string, c ) ) != 0 ) {
if ( next_slash != string ) {
strcpy_lt( buffer, string, (next_slash-string>63)?63:(next_slash-string) );
list_add( list, strdup( buffer ) );
}
string += next_slash - string + 1;
}
if ( string[0] != 0 )
list_add( list, strdup( string ) );
return list;
}
/*
====================================================================
This function reads in a whole file and converts it into a
PData tree struct. If an error occurs NULL is returned and
parser_error is set.
====================================================================
*/
static int parser_read_file_full( FILE *file, PData *top )
{
PData *sub = 0;
char token[1024];
/* parse file */
while ( !feof( file ) ) {
if ( ( sub = parser_parse_file( file ) ) != 0 )
list_add( top->entries, sub );
else
return 0;
/* skip comments and whitespaces */
if ( !file_read_token( file, PARSER_SYMBOLS, PARSER_SKIP_SYMBOLS, token ) ) {
if ( token[0] != 0 )
return 0;
break;
}
else
fseek( file, -strlen( token ), SEEK_CUR );
}
return 1;
}
static int parser_read_file_compact( PData *section )
{
/* section is the parent pdata that needs some
entries */
PData *pd = 0;
char *line, *cur;
while ( ( line = parser_get_next_line() ) ) {
switch ( line[0] ) {
case '>':
/* this section is finished */
return 1;
case '<':
/* add a whole subsection */
pd = calloc( 1, sizeof( PData ) );
pd->name = strdup( line + 1 );
pd->entries = list_create( LIST_NO_AUTO_DELETE, LIST_NO_CALLBACK );
parser_read_file_compact( pd );
/* add to section */
list_add( section->entries, pd );
break;
default:
/* read values as subsection */
pd = calloc( 1, sizeof( PData ) );
/* check name */
if ( ( cur = strchr( line, '»' ) ) == 0 ) {
sprintf( parser_sub_error, "parse error: use '»' for assignment or '<' for section" );
return 0;
}
cur[0] = 0; cur++;
pd->name = strdup( line );
/* get values */
pd->values = parser_explode_string( cur, '°' );
/* add to section */
list_add( section->entries, pd );
break;
}
}
return 1;
}
PData* parser_read_file( char *tree_name, char *fname )
{
int size;
char magic = 0;
FILE *file = 0;
PData *top = 0;
/* open file */
if ( ( file = fopen( fname, "r" ) ) == 0 ) {
sprintf( parser_error, "%s: file not found", fname );
return 0;
}
/* create top level pdata */
top = calloc( 1, sizeof( PData ) );
top->name = strdup( tree_name );
top->entries = list_create( LIST_NO_AUTO_DELETE, LIST_NO_CALLBACK );
/* parse */
FILE_READCHAR( file, magic );
if ( magic == '@' ) {
/* get the whole contents -- 1 and CBUFFER_SIZE are switched */
fseek( file, 0, SEEK_END ); size = ftell( file ) - 2;
if ( size >= CBUFFER_SIZE ) {
fprintf( stderr, "%s: file's too big to fit the compact buffer (128KB)\n", fname );
size = CBUFFER_SIZE - 1;
}
fseek( file, 2, SEEK_SET );
fread( cbuffer, 1, size, file );
cbuffer[size] = 0;
/* set indicator to beginning of text */
cbuffer_pos = cbuffer;
/* parse cbuffer */
if ( !parser_read_file_compact( top ) ) {
parser_set_parse_error( fname, file, parser_sub_error );
goto failure;
}
}
else {
fseek( file, 0, SEEK_SET );
if ( !parser_read_file_full( file, top ) ) {
parser_set_parse_error( fname, file, parser_sub_error );
goto failure;
}
}
/* finalize */
fclose( file );
return top;
failure:
fclose( file );
parser_free( &top );
return 0;
}
/*
====================================================================
This function frees a PData tree struct.
====================================================================
*/
void parser_free( PData **pdata )
{
PData *entry = 0;
if ( (*pdata) == 0 ) return;
if ( (*pdata)->name ) free( (*pdata)->name );
if ( (*pdata)->values ) list_delete( (*pdata)->values );
if ( (*pdata)->entries ) {
list_reset( (*pdata)->entries );
while ( ( entry = list_next( (*pdata)->entries ) ) )
parser_free( &entry );
list_delete( (*pdata)->entries );
}
free( *pdata ); *pdata = 0;
}
/*
====================================================================
Functions to access a PData tree.
'name' is the pass within tree 'pd' where subtrees are separated
by '/' (e.g.: name = 'config/graphics/animations')
parser_get_pdata : get pdata entry associated with 'name'
parser_get_entries : get list of subtrees (PData structs) in 'name'
parser_get_values : get value list of 'name'
parser_get_value : get a single value from value list of 'name'
parser_get_int : get first value of 'name' converted to integer
parser_get_double : get first value of 'name' converted to double
parser_get_string : get first value of 'name' _duplicated_
If an error occurs result is set NULL, False is returned and
parse_error is set.
====================================================================
*/
int parser_get_pdata ( PData *pd, char *name, PData **result )
{
int i, found;
PData *pd_next = pd;
PData *entry = 0;
char *sub = 0;
List *path = parser_explode_string( name, '/' );
for ( i = 0, list_reset( path ); i < path->count; i++ ) {
sub = list_next( path );
if ( !pd_next->entries ) {
sprintf( parser_sub_error, "%s: no subtrees", pd_next->name );
goto failure;
}
list_reset( pd_next->entries ); found = 0;
while ( ( entry = list_next( pd_next->entries ) ) )
if ( strlen( entry->name ) == strlen( sub ) && !strncmp( entry->name, sub, strlen( sub ) ) ) {
pd_next = entry;
found = 1;
break;
}
if ( !found ) {
sprintf( parser_sub_error, "%s: subtree '%s' not found", pd_next->name, sub );
goto failure;
}
}
list_delete( path );
*result = pd_next;
return 1;
failure:
sprintf( parser_error, "parser_get_pdata: %s/%s: %s", pd->name, name, parser_sub_error );
list_delete( path );
*result = 0;
return 0;
}
int parser_get_entries( PData *pd, char *name, List **result )
{
PData *entry;
*result = 0;
if ( !parser_get_pdata( pd, name, &entry ) ) {
sprintf( parser_sub_error, "parser_get_entries:\n %s", parser_error );
strcpy( parser_error, parser_sub_error );
return 0;
}
if ( !entry->entries || entry->entries->count == 0 ) {
sprintf( parser_error, "parser_get_entries: %s/%s: no subtrees", pd->name, name );
return 0;
}
*result = entry->entries;
return 1;
}
int parser_get_values ( PData *pd, char *name, List **result )
{
PData *entry;
*result = 0;
if ( !parser_get_pdata( pd, name, &entry ) ) {
sprintf( parser_sub_error, "parser_get_values:\n %s", parser_error );
strcpy( parser_error, parser_sub_error );
return 0;
}
if ( !entry->values || entry->values->count == 0 ) {
sprintf( parser_error, "parser_get_values: %s/%s: no values", pd->name, name );
return 0;
}
*result = entry->values;
return 1;
}
int parser_get_value ( PData *pd, char *name, char **result, int index )
{
List *values;
if ( !parser_get_values( pd, name, &values ) ) {
sprintf( parser_sub_error, "parser_get_value:\n %s", parser_error );
strcpy( parser_error, parser_sub_error );
return 0;
}
if ( index >= values->count ) {
sprintf( parser_error, "parser_get_value: %s/%s: index %i out of range (%i elements)",
pd->name, name, index, values->count );
return 0;
}
*result = list_get( values, index );
return 1;
}
int parser_get_int ( PData *pd, char *name, int *result )
{
char *value;
if ( !parser_get_value( pd, name, &value, 0 ) ) {
sprintf( parser_sub_error, "parser_get_int:\n %s", parser_error );
strcpy( parser_error, parser_sub_error );
return 0;
}
*result = atoi( value );
return 1;
}
int parser_get_double ( PData *pd, char *name, double *result )
{
char *value;
if ( !parser_get_value( pd, name, &value, 0 ) ) {
sprintf( parser_sub_error, "parser_get_double:\n %s", parser_error );
strcpy( parser_error, parser_sub_error );
return 0;
}
*result = strtod( value, 0 );
return 1;
}
int parser_get_string ( PData *pd, char *name, char **result )
{
char *value;
if ( !parser_get_value( pd, name, &value, 0 ) ) {
sprintf( parser_sub_error, "parser_get_string:\n %s", parser_error );
strcpy( parser_error, parser_sub_error );
return 0;
}
*result = strdup( value );
return 1;
}
/*
====================================================================
If an error occurred you can query the reason with this function.
====================================================================
*/
char* parser_get_error( void )
{
return parser_error;
}

View File

@@ -0,0 +1,150 @@
/***************************************************************************
parser.h - description
-------------------
begin : Sat Mar 9 2002
copyright : (C) 2001 by Michael Speck
email : kulkanie@gmx.net
***************************************************************************/
/***************************************************************************
* *
* 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 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef __PARSER_H
#define __PARSER_H
#include "list.h"
#include <stdio.h>
/*
====================================================================
This module provides functions to parse ASCII data from strings
and files.
Synopsis:
groupname <begin group> entry1 .. entryX <end group>
variable <set> value
A group entry may either be a variable or a group (interlacing).
A variable value may either be a single token or a list of tokens
enclosed by <begin list> <end list>.
Text enclosed by ".." is counted as a single token.
====================================================================
*/
/*
====================================================================
Symbols.
Note: These symbols are ignored when found in a token "<expression>"
as they belong to this token then.
PARSER_GROUP_BEGIN: <begin group>
PARSER_GROUP_END: <end group>
PARSER_SET: <set>
PARSER_LIST_BEGIN: <begin list>
PARSER_LIST_END: <end list>
PARSER_COMMENT_BEGIN: <begin comment>
PARSER_COMMENT_END: <end comment>
PARSER_SYMBOLS: List of all symbols + whitespace used to
split strings and tokens.
PARSER_SKIP_SYMBOLS: text bewteen these two symbols is handled as
comment and therefore completely ignored
====================================================================
*/
#define PARSER_GROUP_BEGIN '{'
#define PARSER_GROUP_END '}'
#define PARSER_SET '='
#define PARSER_LIST_BEGIN '('
#define PARSER_LIST_END ')'
#define PARSER_COMMENT_BEGIN '['
#define PARSER_COMMENT_END ']'
#define PARSER_SYMBOLS " =(){}[]"
#define PARSER_SKIP_SYMBOLS "[]"
/*
====================================================================
An input string is converted into a PData tree struct.
The name identifies this entry and it's the token that is searched
for when reading this entry.
Either 'values' or 'entries' is set.
If 'entries' is not NULL the PData is a group and 'entries'
contains pointers to other groups or lists.
If 'values' is not NULL the PData is a list and 'values' contains
a list of value strings associated with 'name'.
====================================================================
*/
typedef struct {
char *name;
List *values;
List *entries;
} PData;
/*
====================================================================
This function splits a string into tokens using the characters
found in symbols as breakpoints. If the first symbol is ' ' all
whitespaces are used as breakpoints though NOT added as a token
(thus removed from string).
====================================================================
*/
List* parser_split_string( char *string, char *symbols );
/*
====================================================================
This is the light version of parser_split_string which checks for
just one character and does not add this glue characters to the
list. It's about 2% faster. Wow.
====================================================================
*/
List *parser_explode_string( char *string, char c );
/*
====================================================================
This function reads in a whole file and converts it into a
PData tree struct. If an error occurs NULL is returned and
parser_error is set. 'tree_name' is the name of the PData tree.
====================================================================
*/
PData* parser_read_file( char *tree_name, char *fname );
/*
====================================================================
This function frees a PData tree struct.
====================================================================
*/
void parser_free( PData **pdata );
/*
====================================================================
Functions to access a PData tree.
'name' is the pass within tree 'pd' where subtrees are separated
by '/' (e.g.: name = 'config/graphics/animations')
parser_get_pdata : get pdata entry associated with 'name'
parser_get_entries : get list of subtrees (PData structs) in 'name'
parser_get_values : get value list of 'name'
parser_get_value : get a single value from value list of 'name'
parser_get_int : get first value of 'name' converted to integer
parser_get_double : get first value of 'name' converted to double
parser_get_string : get first value of 'name' _duplicated_
If an error occurs result is set NULL, False is returned and
parse_error is set.
====================================================================
*/
int parser_get_pdata ( PData *pd, char *name, PData **result );
int parser_get_entries( PData *pd, char *name, List **result );
int parser_get_values ( PData *pd, char *name, List **result );
int parser_get_value ( PData *pd, char *name, char **result, int index );
int parser_get_int ( PData *pd, char *name, int *result );
int parser_get_double ( PData *pd, char *name, double *result );
int parser_get_string ( PData *pd, char *name, char **result );
/*
====================================================================
If an error occurred you can query the message with this function.
====================================================================
*/
char* parser_get_error( void );
#endif

View File

@@ -0,0 +1,385 @@
/***************************************************************************
tools.c - description
-------------------
begin : Fri Jan 19 2001
copyright : (C) 2001 by Michael Speck
email : kulkanie@gmx.net
***************************************************************************/
/***************************************************************************
* *
* 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 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "tools.h"
/* compares to strings and returns true if their first strlen(str1) chars are equal */
int strequal( char *str1, char *str2 )
{
if ( strlen( str1 ) != strlen( str2 ) ) return 0;
return ( !strncmp( str1, str2, strlen( str1 ) ) );
}
/* set delay to ms milliseconds */
void delay_set( Delay *delay, int ms )
{
delay->limit = ms;
delay->cur = 0;
}
/* reset delay ( cur = 0 )*/
void delay_reset( Delay *delay )
{
delay->cur = 0;
}
/* check if times out and reset */
int delay_timed_out( Delay *delay, int ms )
{
delay->cur += ms;
if ( delay->cur >= delay->limit ) {
delay->cur = 0;
return 1;
}
return 0;
}
void goto_tile( int *x, int *y, int d )
{
/* 0 -up, clockwise, 5 - left up */
switch ( d ) {
case 1:
if ( !( (*x) & 1 ) )
(*y)--;
(*x)++;
break;
case 2:
if ( (*x) & 1 )
(*y)++;
(*x)++;
break;
case 4:
if ( (*x) & 1 )
(*y)++;
(*x)--;
break;
case 5:
if ( !( (*x) & 1 ) )
(*y)--;
(*x)--;
break;
}
}
/* return distance between to map positions */
int get_dist( int x1, int y1, int x2, int y2 )
{
int range = 0;
while ( x1 != x2 || y1 != y2 ) {
/* approach to x2,y2 */
/* 0 -up, clockwise, 5 - left up */
if ( y1 < y2 ) {
if ( x1 < x2 )
goto_tile( &x1, &y1, 2 );
else
if ( x1 > x2 )
goto_tile( &x1, &y1, 4 );
else
y1++;
}
else
if ( y1 > y2 ) {
if ( x1 < x2 )
goto_tile( &x1, &y1, 1 );
else
if ( x1 > x2 )
goto_tile( &x1, &y1, 5 );
else
y1--;
}
else {
if ( x1 < x2 )
x1++;
else
if ( x1 > x2 )
x1--;
}
range++;
}
return range;
}
/* init random seed by using ftime */
void set_random_seed()
{
srand( (unsigned int)time( 0 ) );
}
/* get coordinates from string */
void get_coord( char *str, int *x, int *y )
{
int i;
char *cur_arg = 0;
*x = *y = 0;
/* get position of comma */
for ( i = 0; i < strlen( str ); i++ )
if ( str[i] == ',' ) break;
if ( i == strlen( str ) ) {
fprintf( stderr, "get_coord: no comma found in pair of coordinates '%s'\n", str );
return; /* no comma found */
}
/* y */
cur_arg = str + i + 1;
if ( cur_arg[0] == 0 )
fprintf( stderr, "get_coord: warning: y-coordinate is empty (maybe you left a space between x and comma?)\n" );
*y = atoi( cur_arg );
/* x */
cur_arg = strdup( str ); cur_arg[i] = 0;
*x = atoi( cur_arg );
FREE( cur_arg );
}
/* replace new_lines with spaces in text */
void repl_new_lines( char *text )
{
int i;
for ( i = 0; i < strlen( text ); i++ )
if ( text[i] < 32 )
text[i] = 32;
}
// convert a str into text ( for listbox ) //
// char width is the width of a line in characters //
Text* create_text( char *orig_str, int char_width )
{
int i, j;
char line[256]; /* a line should not exceed this length */
int pos;
int last_space;
int new_line;
Text *text = 0;
char *str = 0;
text = calloc ( 1, sizeof( Text ) );
// maybe orig_str is a constant expression; duplicate for safety //
str = strdup( orig_str );
// replace original new_lines with spaces //
repl_new_lines( str );
/* change some spaces to new_lines, so that the new text fits the wanted line_length */
/* NOTE: '#' means new_line ! */
// if character width is 0 it's just a single line //
if ( char_width > 0 ) {
pos = 0;
while ( pos < strlen( str ) ) {
last_space = 0;
new_line = 0;
i = 0;
while ( !new_line && i < char_width && i + pos < strlen( str ) ) {
switch ( str[pos + i] ) {
case '#': new_line = 1;
case 32: last_space = i; break;
}
i++;
}
if ( i + pos >= strlen( str ) ) break;
if ( last_space == 0 ) {
/* uhh... much to long, we'll have to cut a word into pieces ... */
last_space = char_width / 2;
}
str[pos + last_space] = 10;
pos += last_space;
}
}
/* count lines */
if ( char_width > 0 ) {
for ( i = 0; i < strlen( str ); i++ )
if ( str[i] == 10 )
text->count++;
/* maybe one unfinished line */
if ( str[strlen( str ) - 1] != 10 )
text->count++;
}
else
text->count = 1;
/* get mem */
text->lines = calloc( text->count, sizeof( char* ) );
pos = 0;
/* get all lines */
for ( j = 0; j < text->count; j++ ) {
i = 0;
while ( pos + i < strlen( str ) && str[pos + i] != 10 ) {
line[i] = str[i + pos];
i++;
}
pos += i; pos++;
line[i] = 0;
text->lines[j] = strdup( line );
}
if ( text->count == 0 )
fprintf( stderr, "conv_to_text: warning: line_count is 0\n" );
free( str );
return text;
}
// delete text //
void delete_text( Text *text )
{
int i;
if ( text == 0 ) return;
/*
if ( lines[1][1] == 'e' && lines[1][0] == '<' )
printf( "hallo\n" );
printf( "--- deleting:\n" );
for ( i = 0; i < line_count; i++ ) {
printf( lines[i] );
printf( "\n" );
}*/
if ( text->lines ) {
for ( i = 0; i < text->count; i++ )
if ( text->lines[i] )
free( text->lines[i] );
free( text->lines );
}
free( text );
}
/*
====================================================================
Get type and prefix from string:
type::prefix
Set both pointers 0 if failure.
====================================================================
*/
void get_type_and_prefix( char *arg, char **type, char **prefix )
{
char *first, *second;
*type = *prefix = 0;
first = strtok( arg, ":" );
second = strtok( 0, ":" );
if ( first == 0 || second == 0 ) return;
*type = strdup( first );
*prefix = strdup( second );
}
/*
====================================================================
Replace any existence of character old into new.
====================================================================
*/
void strrepl( char **str, char c_old, char c_new )
{
char *pos;
while ( ( pos = strchr( *str, c_old ) ) != 0 )
pos[0] = c_new;
}
/*
====================================================================
Copy source to dest and at maximum limit chars. Terminate with 0.
====================================================================
*/
void strcpy_lt( char *dest, char *src, int limit )
{
int len = strlen( src );
if ( len > limit ) {
strncpy( dest, src, limit );
dest[limit] = 0;
}
else
strcpy( dest, src );
}
/*
====================================================================
Parse a version string and return the major version and the current
update.
====================================================================
*/
void parse_version( char *string, int *version, int *update )
{
char *ptr = strchr( string, '.' );
if ( ptr ) ptr[0] = 0;
*version = atoi( string );
if ( ptr ) {
ptr++;
*update = atoi( ptr );
if ( *update < 10 && ptr[0] != '0' )
*update *= 10; /* allow stuff like 1.01 */
ptr--;
ptr[0] = '.';
}
else
*update = 0;
}
/* allocate memory or exit with error if out of it */
void *salloc( int num, int size )
{
void *ptr = calloc( num, size );
if ( ptr == 0 ) {
printf( "out of memory\n" );
exit(1);
}
return ptr;
}
/* print contents of pointer raw */
void print_raw( int len, char *buf )
{
int i;
for ( i = 0; i < len; i++ )
printf( "%02x ", (unsigned char) buf[i] );
printf( "\n" );
}
/* check whether a string does only contain letters, digits or
* underscores */
int is_alphanum( char *str )
{
int i;
for ( i = 0; i< strlen(str); i++ )
if ( !((str[i]>=48&&str[i]<=57)||(str[i]>=65&&str[i]<=90)||(str[i]>=97&&str[i]<=122)||str[i]=='_') )
return 0;
return 1;
}

View File

@@ -0,0 +1,129 @@
/***************************************************************************
tools.h - description
-------------------
begin : Fri Jan 19 2001
copyright : (C) 2001 by Michael Speck
email : kulkanie@gmx.net
***************************************************************************/
/***************************************************************************
* *
* 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 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef __TOOLS_H
#define __TOOLS_H
/* this file contains some useful tools */
/* free with a check */
#define FREE( ptr ) { if ( ptr ) free( ptr ); ptr = 0; }
/* check if a serious of flags is set in source */
#define CHECK_FLAGS( source, flags ) ( source & (flags) )
/* return random value between ( and including ) upper,lower limit */
#define RANDOM( lower, upper ) ( ( rand() % ( ( upper ) - ( lower ) + 1 ) ) + ( lower ) )
/* compute distance of two vectors */
#define VEC_DIST( vec1, vec2 ) ( sqrt( ( vec1.x - vec2.x ) * ( vec1.x - vec2.x ) + ( vec1.y - vec2.y ) * ( vec1.y - vec2.y ) ) )
/* return true if strings are fully equal */
#define STRCMP( str1, str2 ) ( ( strlen( str1 ) == strlen( str2 ) ) && !strncmp( str1, str2, strlen( str1 ) ) )
/* return minimum */
#define MINIMUM( a, b ) ((a<b)?a:b)
/* return maximum */
#define MAXIMUM( a, b ) ((a>b)?a:b)
/* square value */
#define SQUARE( x ) ((x)*(x))
/* compares to strings and returns true if their first strlen(str1) chars are equal */
int strequal( char *str1, char *str2 );
/* delete lines */
void delete_lines( char **lines, int line_number );
/* delay struct */
typedef struct {
int limit;
int cur;
} Delay;
/* set delay to ms milliseconds */
void delay_set( Delay *delay, int ms );
/* reset delay ( cur = 0 )*/
void delay_reset( Delay *delay );
/* check if time's out ( add ms milliseconds )and reset */
int delay_timed_out( Delay *delay, int ms );
/* return distance betwteen to map positions */
int get_dist( int x1, int y1, int x2, int y2 );
/* init random seed by using ftime */
void set_random_seed();
/* get coordintaes from string */
void get_coord( char *str, int *x, int *y );
// text structure //
typedef struct {
char **lines;
int count;
} Text;
// convert a str into text ( for listbox ) //
Text* create_text( char *str, int char_width );
// delete text //
void delete_text( Text *text );
/*
====================================================================
Get type and prefix from string:
type::prefix
Set both pointers 0 if failure.
====================================================================
*/
void get_type_and_prefix( char *arg, char **ext, char **prefix );
/*
====================================================================
Replace any existence of character old into new.
====================================================================
*/
void strrepl( char **str, char c_old, char c_new );
/*
====================================================================
Copy source to dest and at maximum limit chars. Terminate with 0.
====================================================================
*/
void strcpy_lt( char *dest, char *src, int limit );
/*
====================================================================
Parse a version string and return the major version and the current
update.
====================================================================
*/
void parse_version( char *string, int *version, int *update );
/* allocate memory or exit with error if out of it */
void *salloc( int num, int size );
/* print contents of pointer raw */
void print_raw( int len, char *buf );
/* check whether a string does only contain letters, digits or
* underscores */
int is_alphanum( char *str );
#endif