matanza-0.13/0000755000175000017500000000000013531314207013237 5ustar boradminboradminmatanza-0.13/xmltok_impl.c0000644000175000017500000011765307254522236015767 0ustar boradminboradmin/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd See the file copying.txt for copying permission. */ #ifndef IS_INVALID_CHAR #define IS_INVALID_CHAR(enc, ptr, n) (0) #endif #define INVALID_LEAD_CASE(n, ptr, nextTokPtr) \ case BT_LEAD ## n: \ if (end - ptr < n) \ return XML_TOK_PARTIAL_CHAR; \ if (IS_INVALID_CHAR(enc, ptr, n)) { \ *(nextTokPtr) = (ptr); \ return XML_TOK_INVALID; \ } \ ptr += n; \ break; #define INVALID_CASES(ptr, nextTokPtr) \ INVALID_LEAD_CASE(2, ptr, nextTokPtr) \ INVALID_LEAD_CASE(3, ptr, nextTokPtr) \ INVALID_LEAD_CASE(4, ptr, nextTokPtr) \ case BT_NONXML: \ case BT_MALFORM: \ case BT_TRAIL: \ *(nextTokPtr) = (ptr); \ return XML_TOK_INVALID; #define CHECK_NAME_CASE(n, enc, ptr, end, nextTokPtr) \ case BT_LEAD ## n: \ if (end - ptr < n) \ return XML_TOK_PARTIAL_CHAR; \ if (!IS_NAME_CHAR(enc, ptr, n)) { \ *nextTokPtr = ptr; \ return XML_TOK_INVALID; \ } \ ptr += n; \ break; #define CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) \ case BT_NONASCII: \ if (!IS_NAME_CHAR_MINBPC(enc, ptr)) { \ *nextTokPtr = ptr; \ return XML_TOK_INVALID; \ } \ case BT_NMSTRT: \ case BT_HEX: \ case BT_DIGIT: \ case BT_NAME: \ case BT_MINUS: \ ptr += MINBPC(enc); \ break; \ CHECK_NAME_CASE(2, enc, ptr, end, nextTokPtr) \ CHECK_NAME_CASE(3, enc, ptr, end, nextTokPtr) \ CHECK_NAME_CASE(4, enc, ptr, end, nextTokPtr) #define CHECK_NMSTRT_CASE(n, enc, ptr, end, nextTokPtr) \ case BT_LEAD ## n: \ if (end - ptr < n) \ return XML_TOK_PARTIAL_CHAR; \ if (!IS_NMSTRT_CHAR(enc, ptr, n)) { \ *nextTokPtr = ptr; \ return XML_TOK_INVALID; \ } \ ptr += n; \ break; #define CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) \ case BT_NONASCII: \ if (!IS_NMSTRT_CHAR_MINBPC(enc, ptr)) { \ *nextTokPtr = ptr; \ return XML_TOK_INVALID; \ } \ case BT_NMSTRT: \ case BT_HEX: \ ptr += MINBPC(enc); \ break; \ CHECK_NMSTRT_CASE(2, enc, ptr, end, nextTokPtr) \ CHECK_NMSTRT_CASE(3, enc, ptr, end, nextTokPtr) \ CHECK_NMSTRT_CASE(4, enc, ptr, end, nextTokPtr) #ifndef PREFIX #define PREFIX(ident) ident #endif /* ptr points to character following " */ switch (BYTE_TYPE(enc, ptr + MINBPC(enc))) { case BT_S: case BT_CR: case BT_LF: case BT_PERCNT: *nextTokPtr = ptr; return XML_TOK_INVALID; } /* fall through */ case BT_S: case BT_CR: case BT_LF: *nextTokPtr = ptr; return XML_TOK_DECL_OPEN; case BT_NMSTRT: case BT_HEX: ptr += MINBPC(enc); break; default: *nextTokPtr = ptr; return XML_TOK_INVALID; } } return XML_TOK_PARTIAL; } static int PREFIX(checkPiTarget)(const ENCODING *enc, const char *ptr, const char *end, int *tokPtr) { int upper = 0; *tokPtr = XML_TOK_PI; if (end - ptr != MINBPC(enc)*3) return 1; switch (BYTE_TO_ASCII(enc, ptr)) { case ASCII_x: break; case ASCII_X: upper = 1; break; default: return 1; } ptr += MINBPC(enc); switch (BYTE_TO_ASCII(enc, ptr)) { case ASCII_m: break; case ASCII_M: upper = 1; break; default: return 1; } ptr += MINBPC(enc); switch (BYTE_TO_ASCII(enc, ptr)) { case ASCII_l: break; case ASCII_L: upper = 1; break; default: return 1; } if (upper) return 0; *tokPtr = XML_TOK_XML_DECL; return 1; } /* ptr points to character following " 1) { size_t n = end - ptr; if (n & (MINBPC(enc) - 1)) { n &= ~(MINBPC(enc) - 1); if (n == 0) return XML_TOK_PARTIAL; end = ptr + n; } } switch (BYTE_TYPE(enc, ptr)) { case BT_RSQB: ptr += MINBPC(enc); if (ptr == end) return XML_TOK_PARTIAL; if (!CHAR_MATCHES(enc, ptr, ASCII_RSQB)) break; ptr += MINBPC(enc); if (ptr == end) return XML_TOK_PARTIAL; if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) { ptr -= MINBPC(enc); break; } *nextTokPtr = ptr + MINBPC(enc); return XML_TOK_CDATA_SECT_CLOSE; case BT_CR: ptr += MINBPC(enc); if (ptr == end) return XML_TOK_PARTIAL; if (BYTE_TYPE(enc, ptr) == BT_LF) ptr += MINBPC(enc); *nextTokPtr = ptr; return XML_TOK_DATA_NEWLINE; case BT_LF: *nextTokPtr = ptr + MINBPC(enc); return XML_TOK_DATA_NEWLINE; INVALID_CASES(ptr, nextTokPtr) default: ptr += MINBPC(enc); break; } while (ptr != end) { switch (BYTE_TYPE(enc, ptr)) { #define LEAD_CASE(n) \ case BT_LEAD ## n: \ if (end - ptr < n || IS_INVALID_CHAR(enc, ptr, n)) { \ *nextTokPtr = ptr; \ return XML_TOK_DATA_CHARS; \ } \ ptr += n; \ break; LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) #undef LEAD_CASE case BT_NONXML: case BT_MALFORM: case BT_TRAIL: case BT_CR: case BT_LF: case BT_RSQB: *nextTokPtr = ptr; return XML_TOK_DATA_CHARS; default: ptr += MINBPC(enc); break; } } *nextTokPtr = ptr; return XML_TOK_DATA_CHARS; } /* ptr points to character following " 1) { size_t n = end - ptr; if (n & (MINBPC(enc) - 1)) { n &= ~(MINBPC(enc) - 1); if (n == 0) return XML_TOK_PARTIAL; end = ptr + n; } } switch (BYTE_TYPE(enc, ptr)) { case BT_LT: return PREFIX(scanLt)(enc, ptr + MINBPC(enc), end, nextTokPtr); case BT_AMP: return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr); case BT_CR: ptr += MINBPC(enc); if (ptr == end) return XML_TOK_TRAILING_CR; if (BYTE_TYPE(enc, ptr) == BT_LF) ptr += MINBPC(enc); *nextTokPtr = ptr; return XML_TOK_DATA_NEWLINE; case BT_LF: *nextTokPtr = ptr + MINBPC(enc); return XML_TOK_DATA_NEWLINE; case BT_RSQB: ptr += MINBPC(enc); if (ptr == end) return XML_TOK_TRAILING_RSQB; if (!CHAR_MATCHES(enc, ptr, ASCII_RSQB)) break; ptr += MINBPC(enc); if (ptr == end) return XML_TOK_TRAILING_RSQB; if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) { ptr -= MINBPC(enc); break; } *nextTokPtr = ptr; return XML_TOK_INVALID; INVALID_CASES(ptr, nextTokPtr) default: ptr += MINBPC(enc); break; } while (ptr != end) { switch (BYTE_TYPE(enc, ptr)) { #define LEAD_CASE(n) \ case BT_LEAD ## n: \ if (end - ptr < n || IS_INVALID_CHAR(enc, ptr, n)) { \ *nextTokPtr = ptr; \ return XML_TOK_DATA_CHARS; \ } \ ptr += n; \ break; LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) #undef LEAD_CASE case BT_RSQB: if (ptr + MINBPC(enc) != end) { if (!CHAR_MATCHES(enc, ptr + MINBPC(enc), ASCII_RSQB)) { ptr += MINBPC(enc); break; } if (ptr + 2*MINBPC(enc) != end) { if (!CHAR_MATCHES(enc, ptr + 2*MINBPC(enc), ASCII_GT)) { ptr += MINBPC(enc); break; } *nextTokPtr = ptr + 2*MINBPC(enc); return XML_TOK_INVALID; } } /* fall through */ case BT_AMP: case BT_LT: case BT_NONXML: case BT_MALFORM: case BT_TRAIL: case BT_CR: case BT_LF: *nextTokPtr = ptr; return XML_TOK_DATA_CHARS; default: ptr += MINBPC(enc); break; } } *nextTokPtr = ptr; return XML_TOK_DATA_CHARS; } /* ptr points to character following "%" */ static int PREFIX(scanPercent)(const ENCODING *enc, const char *ptr, const char *end, const char **nextTokPtr) { if (ptr == end) return XML_TOK_PARTIAL; switch (BYTE_TYPE(enc, ptr)) { CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) case BT_S: case BT_LF: case BT_CR: case BT_PERCNT: *nextTokPtr = ptr; return XML_TOK_PERCENT; default: *nextTokPtr = ptr; return XML_TOK_INVALID; } while (ptr != end) { switch (BYTE_TYPE(enc, ptr)) { CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) case BT_SEMI: *nextTokPtr = ptr + MINBPC(enc); return XML_TOK_PARAM_ENTITY_REF; default: *nextTokPtr = ptr; return XML_TOK_INVALID; } } return XML_TOK_PARTIAL; } static int PREFIX(scanPoundName)(const ENCODING *enc, const char *ptr, const char *end, const char **nextTokPtr) { if (ptr == end) return XML_TOK_PARTIAL; switch (BYTE_TYPE(enc, ptr)) { CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) default: *nextTokPtr = ptr; return XML_TOK_INVALID; } while (ptr != end) { switch (BYTE_TYPE(enc, ptr)) { CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) case BT_CR: case BT_LF: case BT_S: case BT_RPAR: case BT_GT: case BT_PERCNT: case BT_VERBAR: *nextTokPtr = ptr; return XML_TOK_POUND_NAME; default: *nextTokPtr = ptr; return XML_TOK_INVALID; } } return -XML_TOK_POUND_NAME; } static int PREFIX(scanLit)(int open, const ENCODING *enc, const char *ptr, const char *end, const char **nextTokPtr) { while (ptr != end) { int t = BYTE_TYPE(enc, ptr); switch (t) { INVALID_CASES(ptr, nextTokPtr) case BT_QUOT: case BT_APOS: ptr += MINBPC(enc); if (t != open) break; if (ptr == end) return -XML_TOK_LITERAL; *nextTokPtr = ptr; switch (BYTE_TYPE(enc, ptr)) { case BT_S: case BT_CR: case BT_LF: case BT_GT: case BT_PERCNT: case BT_LSQB: return XML_TOK_LITERAL; default: return XML_TOK_INVALID; } default: ptr += MINBPC(enc); break; } } return XML_TOK_PARTIAL; } static int PREFIX(prologTok)(const ENCODING *enc, const char *ptr, const char *end, const char **nextTokPtr) { int tok; if (ptr == end) return XML_TOK_NONE; if (MINBPC(enc) > 1) { size_t n = end - ptr; if (n & (MINBPC(enc) - 1)) { n &= ~(MINBPC(enc) - 1); if (n == 0) return XML_TOK_PARTIAL; end = ptr + n; } } switch (BYTE_TYPE(enc, ptr)) { case BT_QUOT: return PREFIX(scanLit)(BT_QUOT, enc, ptr + MINBPC(enc), end, nextTokPtr); case BT_APOS: return PREFIX(scanLit)(BT_APOS, enc, ptr + MINBPC(enc), end, nextTokPtr); case BT_LT: { ptr += MINBPC(enc); if (ptr == end) return XML_TOK_PARTIAL; switch (BYTE_TYPE(enc, ptr)) { case BT_EXCL: return PREFIX(scanDecl)(enc, ptr + MINBPC(enc), end, nextTokPtr); case BT_QUEST: return PREFIX(scanPi)(enc, ptr + MINBPC(enc), end, nextTokPtr); case BT_NMSTRT: case BT_HEX: case BT_NONASCII: case BT_LEAD2: case BT_LEAD3: case BT_LEAD4: *nextTokPtr = ptr - MINBPC(enc); return XML_TOK_INSTANCE_START; } *nextTokPtr = ptr; return XML_TOK_INVALID; } case BT_CR: if (ptr + MINBPC(enc) == end) return -XML_TOK_PROLOG_S; /* fall through */ case BT_S: case BT_LF: for (;;) { ptr += MINBPC(enc); if (ptr == end) break; switch (BYTE_TYPE(enc, ptr)) { case BT_S: case BT_LF: break; case BT_CR: /* don't split CR/LF pair */ if (ptr + MINBPC(enc) != end) break; /* fall through */ default: *nextTokPtr = ptr; return XML_TOK_PROLOG_S; } } *nextTokPtr = ptr; return XML_TOK_PROLOG_S; case BT_PERCNT: return PREFIX(scanPercent)(enc, ptr + MINBPC(enc), end, nextTokPtr); case BT_COMMA: *nextTokPtr = ptr + MINBPC(enc); return XML_TOK_COMMA; case BT_LSQB: *nextTokPtr = ptr + MINBPC(enc); return XML_TOK_OPEN_BRACKET; case BT_RSQB: ptr += MINBPC(enc); if (ptr == end) return -XML_TOK_CLOSE_BRACKET; if (CHAR_MATCHES(enc, ptr, ASCII_RSQB)) { if (ptr + MINBPC(enc) == end) return XML_TOK_PARTIAL; if (CHAR_MATCHES(enc, ptr + MINBPC(enc), ASCII_GT)) { *nextTokPtr = ptr + 2*MINBPC(enc); return XML_TOK_COND_SECT_CLOSE; } } *nextTokPtr = ptr; return XML_TOK_CLOSE_BRACKET; case BT_LPAR: *nextTokPtr = ptr + MINBPC(enc); return XML_TOK_OPEN_PAREN; case BT_RPAR: ptr += MINBPC(enc); if (ptr == end) return -XML_TOK_CLOSE_PAREN; switch (BYTE_TYPE(enc, ptr)) { case BT_AST: *nextTokPtr = ptr + MINBPC(enc); return XML_TOK_CLOSE_PAREN_ASTERISK; case BT_QUEST: *nextTokPtr = ptr + MINBPC(enc); return XML_TOK_CLOSE_PAREN_QUESTION; case BT_PLUS: *nextTokPtr = ptr + MINBPC(enc); return XML_TOK_CLOSE_PAREN_PLUS; case BT_CR: case BT_LF: case BT_S: case BT_GT: case BT_COMMA: case BT_VERBAR: case BT_RPAR: *nextTokPtr = ptr; return XML_TOK_CLOSE_PAREN; } *nextTokPtr = ptr; return XML_TOK_INVALID; case BT_VERBAR: *nextTokPtr = ptr + MINBPC(enc); return XML_TOK_OR; case BT_GT: *nextTokPtr = ptr + MINBPC(enc); return XML_TOK_DECL_CLOSE; case BT_NUM: return PREFIX(scanPoundName)(enc, ptr + MINBPC(enc), end, nextTokPtr); #define LEAD_CASE(n) \ case BT_LEAD ## n: \ if (end - ptr < n) \ return XML_TOK_PARTIAL_CHAR; \ if (IS_NMSTRT_CHAR(enc, ptr, n)) { \ ptr += n; \ tok = XML_TOK_NAME; \ break; \ } \ if (IS_NAME_CHAR(enc, ptr, n)) { \ ptr += n; \ tok = XML_TOK_NMTOKEN; \ break; \ } \ *nextTokPtr = ptr; \ return XML_TOK_INVALID; LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) #undef LEAD_CASE case BT_NMSTRT: case BT_HEX: tok = XML_TOK_NAME; ptr += MINBPC(enc); break; case BT_DIGIT: case BT_NAME: case BT_MINUS: #ifdef XML_NS case BT_COLON: #endif tok = XML_TOK_NMTOKEN; ptr += MINBPC(enc); break; case BT_NONASCII: if (IS_NMSTRT_CHAR_MINBPC(enc, ptr)) { ptr += MINBPC(enc); tok = XML_TOK_NAME; break; } if (IS_NAME_CHAR_MINBPC(enc, ptr)) { ptr += MINBPC(enc); tok = XML_TOK_NMTOKEN; break; } /* fall through */ default: *nextTokPtr = ptr; return XML_TOK_INVALID; } while (ptr != end) { switch (BYTE_TYPE(enc, ptr)) { CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) case BT_GT: case BT_RPAR: case BT_COMMA: case BT_VERBAR: case BT_LSQB: case BT_PERCNT: case BT_S: case BT_CR: case BT_LF: *nextTokPtr = ptr; return tok; #ifdef XML_NS case BT_COLON: ptr += MINBPC(enc); switch (tok) { case XML_TOK_NAME: if (ptr == end) return XML_TOK_PARTIAL; tok = XML_TOK_PREFIXED_NAME; switch (BYTE_TYPE(enc, ptr)) { CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) default: tok = XML_TOK_NMTOKEN; break; } break; case XML_TOK_PREFIXED_NAME: tok = XML_TOK_NMTOKEN; break; } break; #endif case BT_PLUS: if (tok == XML_TOK_NMTOKEN) { *nextTokPtr = ptr; return XML_TOK_INVALID; } *nextTokPtr = ptr + MINBPC(enc); return XML_TOK_NAME_PLUS; case BT_AST: if (tok == XML_TOK_NMTOKEN) { *nextTokPtr = ptr; return XML_TOK_INVALID; } *nextTokPtr = ptr + MINBPC(enc); return XML_TOK_NAME_ASTERISK; case BT_QUEST: if (tok == XML_TOK_NMTOKEN) { *nextTokPtr = ptr; return XML_TOK_INVALID; } *nextTokPtr = ptr + MINBPC(enc); return XML_TOK_NAME_QUESTION; default: *nextTokPtr = ptr; return XML_TOK_INVALID; } } return -tok; } static int PREFIX(attributeValueTok)(const ENCODING *enc, const char *ptr, const char *end, const char **nextTokPtr) { const char *start; if (ptr == end) return XML_TOK_NONE; start = ptr; while (ptr != end) { switch (BYTE_TYPE(enc, ptr)) { #define LEAD_CASE(n) \ case BT_LEAD ## n: ptr += n; break; LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) #undef LEAD_CASE case BT_AMP: if (ptr == start) return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr); *nextTokPtr = ptr; return XML_TOK_DATA_CHARS; case BT_LT: /* this is for inside entity references */ *nextTokPtr = ptr; return XML_TOK_INVALID; case BT_LF: if (ptr == start) { *nextTokPtr = ptr + MINBPC(enc); return XML_TOK_DATA_NEWLINE; } *nextTokPtr = ptr; return XML_TOK_DATA_CHARS; case BT_CR: if (ptr == start) { ptr += MINBPC(enc); if (ptr == end) return XML_TOK_TRAILING_CR; if (BYTE_TYPE(enc, ptr) == BT_LF) ptr += MINBPC(enc); *nextTokPtr = ptr; return XML_TOK_DATA_NEWLINE; } *nextTokPtr = ptr; return XML_TOK_DATA_CHARS; case BT_S: if (ptr == start) { *nextTokPtr = ptr + MINBPC(enc); return XML_TOK_ATTRIBUTE_VALUE_S; } *nextTokPtr = ptr; return XML_TOK_DATA_CHARS; default: ptr += MINBPC(enc); break; } } *nextTokPtr = ptr; return XML_TOK_DATA_CHARS; } static int PREFIX(entityValueTok)(const ENCODING *enc, const char *ptr, const char *end, const char **nextTokPtr) { const char *start; if (ptr == end) return XML_TOK_NONE; start = ptr; while (ptr != end) { switch (BYTE_TYPE(enc, ptr)) { #define LEAD_CASE(n) \ case BT_LEAD ## n: ptr += n; break; LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) #undef LEAD_CASE case BT_AMP: if (ptr == start) return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr); *nextTokPtr = ptr; return XML_TOK_DATA_CHARS; case BT_PERCNT: if (ptr == start) return PREFIX(scanPercent)(enc, ptr + MINBPC(enc), end, nextTokPtr); *nextTokPtr = ptr; return XML_TOK_DATA_CHARS; case BT_LF: if (ptr == start) { *nextTokPtr = ptr + MINBPC(enc); return XML_TOK_DATA_NEWLINE; } *nextTokPtr = ptr; return XML_TOK_DATA_CHARS; case BT_CR: if (ptr == start) { ptr += MINBPC(enc); if (ptr == end) return XML_TOK_TRAILING_CR; if (BYTE_TYPE(enc, ptr) == BT_LF) ptr += MINBPC(enc); *nextTokPtr = ptr; return XML_TOK_DATA_NEWLINE; } *nextTokPtr = ptr; return XML_TOK_DATA_CHARS; default: ptr += MINBPC(enc); break; } } *nextTokPtr = ptr; return XML_TOK_DATA_CHARS; } #ifdef XML_DTD static int PREFIX(ignoreSectionTok)(const ENCODING *enc, const char *ptr, const char *end, const char **nextTokPtr) { int level = 0; if (MINBPC(enc) > 1) { size_t n = end - ptr; if (n & (MINBPC(enc) - 1)) { n &= ~(MINBPC(enc) - 1); end = ptr + n; } } while (ptr != end) { switch (BYTE_TYPE(enc, ptr)) { INVALID_CASES(ptr, nextTokPtr) case BT_LT: if ((ptr += MINBPC(enc)) == end) return XML_TOK_PARTIAL; if (CHAR_MATCHES(enc, ptr, ASCII_EXCL)) { if ((ptr += MINBPC(enc)) == end) return XML_TOK_PARTIAL; if (CHAR_MATCHES(enc, ptr, ASCII_LSQB)) { ++level; ptr += MINBPC(enc); } } break; case BT_RSQB: if ((ptr += MINBPC(enc)) == end) return XML_TOK_PARTIAL; if (CHAR_MATCHES(enc, ptr, ASCII_RSQB)) { if ((ptr += MINBPC(enc)) == end) return XML_TOK_PARTIAL; if (CHAR_MATCHES(enc, ptr, ASCII_GT)) { ptr += MINBPC(enc); if (level == 0) { *nextTokPtr = ptr; return XML_TOK_IGNORE_SECT; } --level; } } break; default: ptr += MINBPC(enc); break; } } return XML_TOK_PARTIAL; } #endif /* XML_DTD */ static int PREFIX(isPublicId)(const ENCODING *enc, const char *ptr, const char *end, const char **badPtr) { ptr += MINBPC(enc); end -= MINBPC(enc); for (; ptr != end; ptr += MINBPC(enc)) { switch (BYTE_TYPE(enc, ptr)) { case BT_DIGIT: case BT_HEX: case BT_MINUS: case BT_APOS: case BT_LPAR: case BT_RPAR: case BT_PLUS: case BT_COMMA: case BT_SOL: case BT_EQUALS: case BT_QUEST: case BT_CR: case BT_LF: case BT_SEMI: case BT_EXCL: case BT_AST: case BT_PERCNT: case BT_NUM: #ifdef XML_NS case BT_COLON: #endif break; case BT_S: if (CHAR_MATCHES(enc, ptr, ASCII_TAB)) { *badPtr = ptr; return 0; } break; case BT_NAME: case BT_NMSTRT: if (!(BYTE_TO_ASCII(enc, ptr) & ~0x7f)) break; default: switch (BYTE_TO_ASCII(enc, ptr)) { case 0x24: /* $ */ case 0x40: /* @ */ break; default: *badPtr = ptr; return 0; } break; } } return 1; } /* This must only be called for a well-formed start-tag or empty element tag. Returns the number of attributes. Pointers to the first attsMax attributes are stored in atts. */ static int PREFIX(getAtts)(const ENCODING *enc, const char *ptr, int attsMax, ATTRIBUTE *atts) { enum { other, inName, inValue } state = inName; int nAtts = 0; int open = 0; /* defined when state == inValue; initialization just to shut up compilers */ for (ptr += MINBPC(enc);; ptr += MINBPC(enc)) { switch (BYTE_TYPE(enc, ptr)) { #define START_NAME \ if (state == other) { \ if (nAtts < attsMax) { \ atts[nAtts].name = ptr; \ atts[nAtts].normalized = 1; \ } \ state = inName; \ } #define LEAD_CASE(n) \ case BT_LEAD ## n: START_NAME ptr += (n - MINBPC(enc)); break; LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) #undef LEAD_CASE case BT_NONASCII: case BT_NMSTRT: case BT_HEX: START_NAME break; #undef START_NAME case BT_QUOT: if (state != inValue) { if (nAtts < attsMax) atts[nAtts].valuePtr = ptr + MINBPC(enc); state = inValue; open = BT_QUOT; } else if (open == BT_QUOT) { state = other; if (nAtts < attsMax) atts[nAtts].valueEnd = ptr; nAtts++; } break; case BT_APOS: if (state != inValue) { if (nAtts < attsMax) atts[nAtts].valuePtr = ptr + MINBPC(enc); state = inValue; open = BT_APOS; } else if (open == BT_APOS) { state = other; if (nAtts < attsMax) atts[nAtts].valueEnd = ptr; nAtts++; } break; case BT_AMP: if (nAtts < attsMax) atts[nAtts].normalized = 0; break; case BT_S: if (state == inName) state = other; else if (state == inValue && nAtts < attsMax && atts[nAtts].normalized && (ptr == atts[nAtts].valuePtr || BYTE_TO_ASCII(enc, ptr) != ASCII_SPACE || BYTE_TO_ASCII(enc, ptr + MINBPC(enc)) == ASCII_SPACE || BYTE_TYPE(enc, ptr + MINBPC(enc)) == open)) atts[nAtts].normalized = 0; break; case BT_CR: case BT_LF: /* This case ensures that the first attribute name is counted Apart from that we could just change state on the quote. */ if (state == inName) state = other; else if (state == inValue && nAtts < attsMax) atts[nAtts].normalized = 0; break; case BT_GT: case BT_SOL: if (state != inValue) return nAtts; break; default: break; } } /* not reached */ } static int PREFIX(charRefNumber)(const ENCODING *enc, const char *ptr) { int result = 0; /* skip &# */ ptr += 2*MINBPC(enc); if (CHAR_MATCHES(enc, ptr, ASCII_x)) { for (ptr += MINBPC(enc); !CHAR_MATCHES(enc, ptr, ASCII_SEMI); ptr += MINBPC(enc)) { int c = BYTE_TO_ASCII(enc, ptr); switch (c) { case ASCII_0: case ASCII_1: case ASCII_2: case ASCII_3: case ASCII_4: case ASCII_5: case ASCII_6: case ASCII_7: case ASCII_8: case ASCII_9: result <<= 4; result |= (c - ASCII_0); break; case ASCII_A: case ASCII_B: case ASCII_C: case ASCII_D: case ASCII_E: case ASCII_F: result <<= 4; result += 10 + (c - ASCII_A); break; case ASCII_a: case ASCII_b: case ASCII_c: case ASCII_d: case ASCII_e: case ASCII_f: result <<= 4; result += 10 + (c - ASCII_a); break; } if (result >= 0x110000) return -1; } } else { for (; !CHAR_MATCHES(enc, ptr, ASCII_SEMI); ptr += MINBPC(enc)) { int c = BYTE_TO_ASCII(enc, ptr); result *= 10; result += (c - ASCII_0); if (result >= 0x110000) return -1; } } return checkCharRefNumber(result); } static int PREFIX(predefinedEntityName)(const ENCODING *enc, const char *ptr, const char *end) { switch ((end - ptr)/MINBPC(enc)) { case 2: if (CHAR_MATCHES(enc, ptr + MINBPC(enc), ASCII_t)) { switch (BYTE_TO_ASCII(enc, ptr)) { case ASCII_l: return ASCII_LT; case ASCII_g: return ASCII_GT; } } break; case 3: if (CHAR_MATCHES(enc, ptr, ASCII_a)) { ptr += MINBPC(enc); if (CHAR_MATCHES(enc, ptr, ASCII_m)) { ptr += MINBPC(enc); if (CHAR_MATCHES(enc, ptr, ASCII_p)) return ASCII_AMP; } } break; case 4: switch (BYTE_TO_ASCII(enc, ptr)) { case ASCII_q: ptr += MINBPC(enc); if (CHAR_MATCHES(enc, ptr, ASCII_u)) { ptr += MINBPC(enc); if (CHAR_MATCHES(enc, ptr, ASCII_o)) { ptr += MINBPC(enc); if (CHAR_MATCHES(enc, ptr, ASCII_t)) return ASCII_QUOT; } } break; case ASCII_a: ptr += MINBPC(enc); if (CHAR_MATCHES(enc, ptr, ASCII_p)) { ptr += MINBPC(enc); if (CHAR_MATCHES(enc, ptr, ASCII_o)) { ptr += MINBPC(enc); if (CHAR_MATCHES(enc, ptr, ASCII_s)) return ASCII_APOS; } } break; } } return 0; } static int PREFIX(sameName)(const ENCODING *enc, const char *ptr1, const char *ptr2) { for (;;) { switch (BYTE_TYPE(enc, ptr1)) { #define LEAD_CASE(n) \ case BT_LEAD ## n: \ if (*ptr1++ != *ptr2++) \ return 0; LEAD_CASE(4) LEAD_CASE(3) LEAD_CASE(2) #undef LEAD_CASE /* fall through */ if (*ptr1++ != *ptr2++) return 0; break; case BT_NONASCII: case BT_NMSTRT: #ifdef XML_NS case BT_COLON: #endif case BT_HEX: case BT_DIGIT: case BT_NAME: case BT_MINUS: if (*ptr2++ != *ptr1++) return 0; if (MINBPC(enc) > 1) { if (*ptr2++ != *ptr1++) return 0; if (MINBPC(enc) > 2) { if (*ptr2++ != *ptr1++) return 0; if (MINBPC(enc) > 3) { if (*ptr2++ != *ptr1++) return 0; } } } break; default: if (MINBPC(enc) == 1 && *ptr1 == *ptr2) return 1; switch (BYTE_TYPE(enc, ptr2)) { case BT_LEAD2: case BT_LEAD3: case BT_LEAD4: case BT_NONASCII: case BT_NMSTRT: #ifdef XML_NS case BT_COLON: #endif case BT_HEX: case BT_DIGIT: case BT_NAME: case BT_MINUS: return 0; default: return 1; } } } /* not reached */ } static int PREFIX(nameMatchesAscii)(const ENCODING *enc, const char *ptr1, const char *end1, const char *ptr2) { for (; *ptr2; ptr1 += MINBPC(enc), ptr2++) { if (ptr1 == end1) return 0; if (!CHAR_MATCHES(enc, ptr1, *ptr2)) return 0; } return ptr1 == end1; } static int PREFIX(nameLength)(const ENCODING *enc, const char *ptr) { const char *start = ptr; for (;;) { switch (BYTE_TYPE(enc, ptr)) { #define LEAD_CASE(n) \ case BT_LEAD ## n: ptr += n; break; LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) #undef LEAD_CASE case BT_NONASCII: case BT_NMSTRT: #ifdef XML_NS case BT_COLON: #endif case BT_HEX: case BT_DIGIT: case BT_NAME: case BT_MINUS: ptr += MINBPC(enc); break; default: return ptr - start; } } } static const char *PREFIX(skipS)(const ENCODING *enc, const char *ptr) { for (;;) { switch (BYTE_TYPE(enc, ptr)) { case BT_LF: case BT_CR: case BT_S: ptr += MINBPC(enc); break; default: return ptr; } } } static void PREFIX(updatePosition)(const ENCODING *enc, const char *ptr, const char *end, POSITION *pos) { while (ptr != end) { switch (BYTE_TYPE(enc, ptr)) { #define LEAD_CASE(n) \ case BT_LEAD ## n: \ ptr += n; \ break; LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) #undef LEAD_CASE case BT_LF: pos->columnNumber = (unsigned)-1; pos->lineNumber++; ptr += MINBPC(enc); break; case BT_CR: pos->lineNumber++; ptr += MINBPC(enc); if (ptr != end && BYTE_TYPE(enc, ptr) == BT_LF) ptr += MINBPC(enc); pos->columnNumber = (unsigned)-1; break; default: ptr += MINBPC(enc); break; } pos->columnNumber++; } } #undef DO_LEAD_CASE #undef MULTIBYTE_CASES #undef INVALID_CASES #undef CHECK_NAME_CASE #undef CHECK_NAME_CASES #undef CHECK_NMSTRT_CASE #undef CHECK_NMSTRT_CASES matanza-0.13/nametab.h0000644000175000017500000001561207254453527015042 0ustar boradminboradminstatic const unsigned namingBitmap[] = { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x04000000, 0x87FFFFFE, 0x07FFFFFE, 0x00000000, 0x00000000, 0xFF7FFFFF, 0xFF7FFFFF, 0xFFFFFFFF, 0x7FF3FFFF, 0xFFFFFDFE, 0x7FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFE00F, 0xFC31FFFF, 0x00FFFFFF, 0x00000000, 0xFFFF0000, 0xFFFFFFFF, 0xFFFFFFFF, 0xF80001FF, 0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xFFFFD740, 0xFFFFFFFB, 0x547F7FFF, 0x000FFFFD, 0xFFFFDFFE, 0xFFFFFFFF, 0xDFFEFFFF, 0xFFFFFFFF, 0xFFFF0003, 0xFFFFFFFF, 0xFFFF199F, 0x033FCFFF, 0x00000000, 0xFFFE0000, 0x027FFFFF, 0xFFFFFFFE, 0x0000007F, 0x00000000, 0xFFFF0000, 0x000707FF, 0x00000000, 0x07FFFFFE, 0x000007FE, 0xFFFE0000, 0xFFFFFFFF, 0x7CFFFFFF, 0x002F7FFF, 0x00000060, 0xFFFFFFE0, 0x23FFFFFF, 0xFF000000, 0x00000003, 0xFFF99FE0, 0x03C5FDFF, 0xB0000000, 0x00030003, 0xFFF987E0, 0x036DFDFF, 0x5E000000, 0x001C0000, 0xFFFBAFE0, 0x23EDFDFF, 0x00000000, 0x00000001, 0xFFF99FE0, 0x23CDFDFF, 0xB0000000, 0x00000003, 0xD63DC7E0, 0x03BFC718, 0x00000000, 0x00000000, 0xFFFDDFE0, 0x03EFFDFF, 0x00000000, 0x00000003, 0xFFFDDFE0, 0x03EFFDFF, 0x40000000, 0x00000003, 0xFFFDDFE0, 0x03FFFDFF, 0x00000000, 0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFE, 0x000D7FFF, 0x0000003F, 0x00000000, 0xFEF02596, 0x200D6CAE, 0x0000001F, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFEFF, 0x000003FF, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFF003F, 0x007FFFFF, 0x0007DAED, 0x50000000, 0x82315001, 0x002C62AB, 0x40000000, 0xF580C900, 0x00000007, 0x02010800, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x03FFFFFF, 0x3F3FFFFF, 0xFFFFFFFF, 0xAAFF3F3F, 0x3FFFFFFF, 0xFFFFFFFF, 0x5FDFFFFF, 0x0FCF1FDC, 0x1FDC1FFF, 0x00000000, 0x00004C40, 0x00000000, 0x00000000, 0x00000007, 0x00000000, 0x00000000, 0x00000000, 0x00000080, 0x000003FE, 0xFFFFFFFE, 0xFFFFFFFF, 0x001FFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0x07FFFFFF, 0xFFFFFFE0, 0x00001FFF, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0000003F, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0000000F, 0x00000000, 0x00000000, 0x00000000, 0x07FF6000, 0x87FFFFFE, 0x07FFFFFE, 0x00000000, 0x00800000, 0xFF7FFFFF, 0xFF7FFFFF, 0x00FFFFFF, 0x00000000, 0xFFFF0000, 0xFFFFFFFF, 0xFFFFFFFF, 0xF80001FF, 0x00030003, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x0000003F, 0x00000003, 0xFFFFD7C0, 0xFFFFFFFB, 0x547F7FFF, 0x000FFFFD, 0xFFFFDFFE, 0xFFFFFFFF, 0xDFFEFFFF, 0xFFFFFFFF, 0xFFFF007B, 0xFFFFFFFF, 0xFFFF199F, 0x033FCFFF, 0x00000000, 0xFFFE0000, 0x027FFFFF, 0xFFFFFFFE, 0xFFFE007F, 0xBBFFFFFB, 0xFFFF0016, 0x000707FF, 0x00000000, 0x07FFFFFE, 0x0007FFFF, 0xFFFF03FF, 0xFFFFFFFF, 0x7CFFFFFF, 0xFFEF7FFF, 0x03FF3DFF, 0xFFFFFFEE, 0xF3FFFFFF, 0xFF1E3FFF, 0x0000FFCF, 0xFFF99FEE, 0xD3C5FDFF, 0xB080399F, 0x0003FFCF, 0xFFF987E4, 0xD36DFDFF, 0x5E003987, 0x001FFFC0, 0xFFFBAFEE, 0xF3EDFDFF, 0x00003BBF, 0x0000FFC1, 0xFFF99FEE, 0xF3CDFDFF, 0xB0C0398F, 0x0000FFC3, 0xD63DC7EC, 0xC3BFC718, 0x00803DC7, 0x0000FF80, 0xFFFDDFEE, 0xC3EFFDFF, 0x00603DDF, 0x0000FFC3, 0xFFFDDFEC, 0xC3EFFDFF, 0x40603DDF, 0x0000FFC3, 0xFFFDDFEC, 0xC3FFFDFF, 0x00803DCF, 0x0000FFC3, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFE, 0x07FF7FFF, 0x03FF7FFF, 0x00000000, 0xFEF02596, 0x3BFF6CAE, 0x03FF3F5F, 0x00000000, 0x03000000, 0xC2A003FF, 0xFFFFFEFF, 0xFFFE03FF, 0xFEBF0FDF, 0x02FE3FFF, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x1FFF0000, 0x00000002, 0x000000A0, 0x003EFFFE, 0xFFFFFFFE, 0xFFFFFFFF, 0x661FFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0x77FFFFFF, }; static const unsigned char nmstrtPages[] = { 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00, 0x00, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x13, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; static const unsigned char namePages[] = { 0x19, 0x03, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x00, 0x00, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x13, 0x26, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; matanza-0.13/TODO0000644000175000017500000000312407261215111013724 0ustar boradminboradminHere are pending things and ideas and instructions on how to contribute: - Add a flame to the ships, its intensity determined by their speed. - Draw more ships. Please open ship.txt and edit the ship on it. Send me the results. - Finish specifing and implementing MMP. - Add colors. This is not so easy, but must be done. - Add a key to brake the ship as soon as possible. - Make more simple, stupid alien ships. - Make computer controled ships. As smart as can be. - Make an image for the mother ship of every team. Someone do this and send me the result. The mother ship should have wholes for ships to enter into her and come outside of her. The goal of every team is destroying the other teams' mother ships. - Get teams to work again. - When a player gets hurt badly, make his ship suffer random problems: not being able to reach full speed, suddently turning to a given side, etc. - When a player gets hurt badly, make parts of his ship (eg. wings) disappear. - Make special flying pills; when the players hit them, they get bonuses (such as more bullets, health, speeds enhacements and invisibility). - Let the players assemble their ships at the beginning. They must be able to choose how many missiles, fuel, invisibility, radars, etc. they want. - Add fuel. Players will eventually run out of fuel. - Add scores. - Fix the widgets when you have ppc != 1. Improve them. - Add XML configuration for the keyboard. - Improve support for worlds. - Make it possible to specify the damage players get done when they crash against the different objects. In the XML files. matanza-0.13/Makefile.in0000644000175000017500000002624707263463463015335 0ustar boradminboradmin# Makefile.in generated automatically by automake 1.4 from Makefile.am # Copyright (C) 1994, 1995-8, 1999 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. SHELL = @SHELL@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ sbindir = @sbindir@ libexecdir = @libexecdir@ datadir = @datadir@ sysconfdir = @sysconfdir@ sharedstatedir = @sharedstatedir@ localstatedir = @localstatedir@ libdir = @libdir@ infodir = @infodir@ mandir = @mandir@ includedir = @includedir@ oldincludedir = /usr/include DESTDIR = pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = . ACLOCAL = @ACLOCAL@ AUTOCONF = @AUTOCONF@ AUTOMAKE = @AUTOMAKE@ AUTOHEADER = @AUTOHEADER@ INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) INSTALL_DATA = @INSTALL_DATA@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ transform = @program_transform_name@ NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : CC = @CC@ LN_S = @LN_S@ MAKEINFO = @MAKEINFO@ PACKAGE = @PACKAGE@ VERSION = @VERSION@ bin_PROGRAMS = matanza matanza-ai matanza_ai_SOURCES = ai.c getopt.h getopt.c getopt1.c EXTRA_matanza_ai_SOURCES = mmp.h matanza_SOURCES = matanza.c getopt.h getopt.c getopt1.c xmlparse.h xmlrole.h xmltok.h xmlparse.c xmlrole.c xmltok.c xmldef.h ascii.h asciitab.h iasciitab.h latin1tab.h nametab.h utf8tab.h BUILT_SOURCES = matanza.c ai.c EXTRA_matanza_SOURCES = shipreal.c mmp.h winconfig.h xmltok_impl.c xmltok_impl.h xmltok_ns.c EXTRA_DIST = matanza.w ai.w TODO ship.txt shiptank.txt matanza.xml maze.png ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = config.h CONFIG_CLEAN_FILES = PROGRAMS = $(bin_PROGRAMS) DEFS = @DEFS@ -I. -I$(srcdir) -I. CPPFLAGS = @CPPFLAGS@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ matanza_OBJECTS = matanza.o getopt.o getopt1.o xmlparse.o xmlrole.o \ xmltok.o matanza_LDADD = $(LDADD) matanza_DEPENDENCIES = matanza_LDFLAGS = matanza_ai_OBJECTS = ai.o getopt.o getopt1.o matanza_ai_LDADD = $(LDADD) matanza_ai_DEPENDENCIES = matanza_ai_LDFLAGS = CFLAGS = @CFLAGS@ COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ DIST_COMMON = README ./stamp-h.in AUTHORS COPYING ChangeLog INSTALL \ Makefile.am Makefile.in NEWS TODO acconfig.h aclocal.m4 config.h.in \ configure configure.in install-sh missing mkinstalldirs DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) TAR = tar GZIP_ENV = --best SOURCES = $(matanza_SOURCES) $(EXTRA_matanza_SOURCES) $(matanza_ai_SOURCES) $(EXTRA_matanza_ai_SOURCES) OBJECTS = $(matanza_OBJECTS) $(matanza_ai_OBJECTS) all: all-redirect .SUFFIXES: .SUFFIXES: .S .c .o .s $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) \ && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status $(ACLOCAL_M4): configure.in cd $(srcdir) && $(ACLOCAL) config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(srcdir)/configure: $(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES) cd $(srcdir) && $(AUTOCONF) config.h: stamp-h @if test ! -f $@; then \ rm -f stamp-h; \ $(MAKE) stamp-h; \ else :; fi stamp-h: $(srcdir)/config.h.in $(top_builddir)/config.status cd $(top_builddir) \ && CONFIG_FILES= CONFIG_HEADERS=config.h \ $(SHELL) ./config.status @echo timestamp > stamp-h 2> /dev/null $(srcdir)/config.h.in: $(srcdir)/stamp-h.in @if test ! -f $@; then \ rm -f $(srcdir)/stamp-h.in; \ $(MAKE) $(srcdir)/stamp-h.in; \ else :; fi $(srcdir)/stamp-h.in: $(top_srcdir)/configure.in $(ACLOCAL_M4) acconfig.h cd $(top_srcdir) && $(AUTOHEADER) @echo timestamp > $(srcdir)/stamp-h.in 2> /dev/null mostlyclean-hdr: clean-hdr: distclean-hdr: -rm -f config.h maintainer-clean-hdr: mostlyclean-binPROGRAMS: clean-binPROGRAMS: -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) distclean-binPROGRAMS: maintainer-clean-binPROGRAMS: install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) $(mkinstalldirs) $(DESTDIR)$(bindir) @list='$(bin_PROGRAMS)'; for p in $$list; do \ if test -f $$p; then \ echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \ $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \ else :; fi; \ done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) list='$(bin_PROGRAMS)'; for p in $$list; do \ rm -f $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \ done .c.o: $(COMPILE) -c $< .s.o: $(COMPILE) -c $< .S.o: $(COMPILE) -c $< mostlyclean-compile: -rm -f *.o core *.core clean-compile: distclean-compile: -rm -f *.tab.c maintainer-clean-compile: matanza: $(matanza_OBJECTS) $(matanza_DEPENDENCIES) @rm -f matanza $(LINK) $(matanza_LDFLAGS) $(matanza_OBJECTS) $(matanza_LDADD) $(LIBS) matanza-ai: $(matanza_ai_OBJECTS) $(matanza_ai_DEPENDENCIES) @rm -f matanza-ai $(LINK) $(matanza_ai_LDFLAGS) $(matanza_ai_OBJECTS) $(matanza_ai_LDADD) $(LIBS) tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) list='$(SOURCES) $(HEADERS)'; \ unique=`for i in $$list; do echo $$i; done | \ awk ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ here=`pwd` && cd $(srcdir) \ && mkid -f$$here/ID $$unique $(LISP) TAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS)'; \ unique=`for i in $$list; do echo $$i; done | \ awk ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(ETAGS_ARGS)config.h.in$$unique$(LISP)$$tags" \ || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags config.h.in $$unique $(LISP) -o $$here/TAGS) mostlyclean-tags: clean-tags: distclean-tags: -rm -f TAGS ID maintainer-clean-tags: distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) # This target untars the dist file and tries a VPATH configuration. Then # it guarantees that the distribution is self-contained by making another # tarfile. distcheck: dist -rm -rf $(distdir) GZIP=$(GZIP_ENV) $(TAR) zxf $(distdir).tar.gz mkdir $(distdir)/=build mkdir $(distdir)/=inst dc_install_base=`cd $(distdir)/=inst && pwd`; \ cd $(distdir)/=build \ && ../configure --srcdir=.. --prefix=$$dc_install_base \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) check \ && $(MAKE) $(AM_MAKEFLAGS) install \ && $(MAKE) $(AM_MAKEFLAGS) installcheck \ && $(MAKE) $(AM_MAKEFLAGS) dist -rm -rf $(distdir) @banner="$(distdir).tar.gz is ready for distribution"; \ dashes=`echo "$$banner" | sed s/./=/g`; \ echo "$$dashes"; \ echo "$$banner"; \ echo "$$dashes" dist: distdir -chmod -R a+r $(distdir) GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir) -rm -rf $(distdir) dist-all: distdir -chmod -R a+r $(distdir) GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir) -rm -rf $(distdir) distdir: $(DISTFILES) -rm -rf $(distdir) mkdir $(distdir) -chmod 777 $(distdir) @for file in $(DISTFILES); do \ d=$(srcdir); \ if test -d $$d/$$file; then \ cp -pr $$/$$file $(distdir)/$$file; \ else \ test -f $(distdir)/$$file \ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ || cp -p $$d/$$file $(distdir)/$$file || :; \ fi; \ done ai.o: ai.c config.h getopt.h shipreal.c mmp.h matanza.o: matanza.c config.h getopt.h xmlparse.h shipreal.c mmp.h xmlparse.o: xmlparse.c xmldef.h xmlparse.h xmltok.h xmlrole.h xmlrole.o: xmlrole.c xmldef.h xmlrole.h xmltok.h ascii.h xmltok.o: xmltok.c xmldef.h xmltok.h nametab.h xmltok_impl.h ascii.h \ xmltok_impl.c asciitab.h utf8tab.h iasciitab.h latin1tab.h \ xmltok_ns.c info-am: info: info-am dvi-am: dvi: dvi-am check-am: all-am check: check-am installcheck-am: installcheck: installcheck-am all-recursive-am: config.h $(MAKE) $(AM_MAKEFLAGS) all-recursive install-exec-am: install-binPROGRAMS install-exec: install-exec-am install-data-am: install-data: install-data-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am install: install-am uninstall-am: uninstall-binPROGRAMS uninstall: uninstall-am all-am: Makefile $(PROGRAMS) config.h all-redirect: all-am install-strip: $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install installdirs: $(mkinstalldirs) $(DESTDIR)$(bindir) mostlyclean-generic: clean-generic: distclean-generic: -rm -f Makefile $(CONFIG_CLEAN_FILES) -rm -f config.cache config.log stamp-h stamp-h[0-9]* maintainer-clean-generic: -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) mostlyclean-am: mostlyclean-hdr mostlyclean-binPROGRAMS \ mostlyclean-compile mostlyclean-tags \ mostlyclean-generic mostlyclean: mostlyclean-am clean-am: clean-hdr clean-binPROGRAMS clean-compile clean-tags \ clean-generic mostlyclean-am clean: clean-am distclean-am: distclean-hdr distclean-binPROGRAMS distclean-compile \ distclean-tags distclean-generic clean-am distclean: distclean-am -rm -f config.status maintainer-clean-am: maintainer-clean-hdr maintainer-clean-binPROGRAMS \ maintainer-clean-compile maintainer-clean-tags \ maintainer-clean-generic distclean-am @echo "This command is intended for maintainers to use;" @echo "it deletes files that may require special tools to rebuild." maintainer-clean: maintainer-clean-am -rm -f config.status .PHONY: mostlyclean-hdr distclean-hdr clean-hdr maintainer-clean-hdr \ mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \ maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \ mostlyclean-compile distclean-compile clean-compile \ maintainer-clean-compile tags mostlyclean-tags distclean-tags \ clean-tags maintainer-clean-tags distdir info-am info dvi-am dvi check \ check-am installcheck-am installcheck all-recursive-am install-exec-am \ install-exec install-data-am install-data install-am install \ uninstall-am uninstall all-redirect all-am all installdirs \ mostlyclean-generic distclean-generic clean-generic \ maintainer-clean-generic clean mostlyclean distclean maintainer-clean matanza.c: matanza.w ctangle matanza.w ai.c: ai.w ctangle ai.w # 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: matanza-0.13/ai.w0000644000175000017500000006511407254740173014041 0ustar boradminboradmin@* Matanza - Artificial Inteligence System @c @ @ @ @ @ @ @ @ @d AI_SCREEN_HEIGHT 24 @d AI_SCREEN_WIDTH 80 @= char screen_buffer[AI_SCREEN_HEIGHT * AI_SCREEN_WIDTH]; char *program_name; FILE *mat_server_in; FILE *mat_server_out; void (*input_process) ( unsigned int ) = input_process_initial; void (*input_process_done) ( void ); char *input_string; int input_string_siz; int input_string_len; int input_number; int input_number_bytes; @ Our standard hashing function. @= unsigned long fhash (char *name) { unsigned long h = 0; unsigned long g; ASSERT(name); /* Our hashing function. */ while ( *name ) { h = ( h << 4 ) + tolower(*name++); if ( (g = h & 0xF0000000) ) h ^= g >> 24; h &= ~g; } return h; } @ @= unsigned long fhash (char *name); @ @= int main ( int argc, char **argv ) { @; while (1) { @; usleep(10000); } } @* Network Input In this big section we are placing all the code that is somehow related to reading input from the network. @ The following functions handle input from the network. @= void input_process_initial ( unsigned int c ); void input_process_close ( unsigned int c ); void input_process_string ( unsigned int c ); void input_process_number ( unsigned int c ); void input_process_default ( unsigned int c ); void input_process_joinfail ( unsigned int c ); void input_process_frame ( unsigned int c ); @ The following functions can be called after a string is read (by |input_process_string). For example, if you get the code for an error, you'll set |input_process| to |input_process_string| and |input_process_done| to |input_process_syserror|. That way, all characters received are passed to |input_process_string|, which stores them on |input_string|, and once it's done, it will call |input_process_done|, which will do something useful with the string. @= void input_process_shiprm_un ( void ); void input_process_shiprm_name ( void ); void input_process_frame_ships ( void ); void input_process_shipname ( void ); void input_process_mmperror ( void ); void input_process_syserror ( void ); void input_process_connect_server_id ( void ); void input_process_connect_server_version ( void ); void input_process_frame_ships_name ( void ); void input_process_frame_ships_x ( void ); void input_process_frame_ships_y ( void ); void input_process_frame_ships_ang ( void ); void input_process_shipadd_other_un ( void ); void input_process_shipadd_other_name ( void ); @ When we are in the Close state, we must wait for a code to report the reason why the server is closing the connection and act accordingly. In the case of an error, we wait for the description before termination. Otherwise, we show a message about the problem and terminate. @= void input_process_close ( unsigned int c ) { switch (c) { case MMP_SERVER_CLOSE_SYSERROR: input_process = input_process_string; input_process_done = input_process_syserror; break; case MMP_SERVER_CLOSE_MMPERROR: input_process = input_process_string; input_process_done = input_process_mmperror; break; case MMP_SERVER_CLOSE_SHUTDOWN: fprintf(stderr, "%s: Server is being shutdown.\n", program_name); exit(EXIT_FAILURE); break; case MMP_SERVER_CLOSE_CLIENT: fprintf(stderr, "%s: Server is closing the connection.\n", program_name); exit(EXIT_FAILURE); break; } } @ When the server had an error, we simply print its description and terminate. @= void input_process_syserror ( void ) { fprintf(stderr, "%s: Server error: %s\n", program_name, input_string); exit(EXIT_FAILURE); } @ When the server reported a violation of MMP, we just terminate. @= void input_process_mmperror ( void ) { fprintf(stderr, "%s: Server reported violation of MMP: %s\n", program_name, input_string); exit(EXIT_FAILURE); } @ When we are in the initial state, we wait for the three valid messages described in the protocol.h file. @= void input_process_initial ( unsigned int c ) { switch(c) { case MMP_SERVER_INITIAL_FULL: @; break; case MMP_SERVER_CLOSE: input_process = input_process_close; break; case MMP_SERVER_INITIAL_CONNECTED: @; break; default: fprintf(stderr, "Unknown message: [msg:%d][state:Initial]\n", c); break; } } @ If the server is full, there is no use in going on. We show a message and terminate. @= { fprintf(stderr, "%s: Server full\n", program_name); exit(EXIT_FAILURE); } @ When we receive the |MMP_SERVER_INITIAL_CONNECTED| message, we read the server's id and version and report it to the user. @= { input_string = NULL; input_string_len = 0; input_string_siz = 0; input_process = input_process_string; input_process_done = input_process_connect_server_id; } @ @= void input_process_string ( unsigned int c ) { if (input_string_len == input_string_siz) @@; input_string[input_string_len ++] = c; if (c == 0) input_process_done(); } @ @= { input_string_siz = input_string_siz ? input_string_siz * 2 : 256; input_string = realloc(input_string, input_string_siz + 1); if (!input_string) { fprintf(stderr, "%s: realloc: %s\n", program_name, strerror(errno)); exit(EXIT_FAILURE); } } @ When this function gets called, the server's id is left in |input_string|. @= void input_process_connect_server_id () { printf("Server: %s\n", input_string ? input_string : ""); free(input_string); input_string = NULL; input_string_len = 0; input_string_siz = 0; input_process = input_process_string; input_process_done = input_process_connect_server_version; } @ When this function gets called, the server's version is at |input_string|. @= void input_process_connect_server_version () { input_process = input_process_default; printf("Server version: %s\n", input_string ? input_string : "Unknown"); free(input_string); fprintf(mat_server_out, "%c%c%c", MMP_CLIENT_DEFAULT_JOIN, 0, 0); fflush(mat_server_out); } @ @= void input_process_default ( unsigned int c ) { /*VERBOSE("Command: %d\n", c);*/ switch (c) { case MMP_SERVER_DEFAULT_JOIN_OK: @; break; case MMP_SERVER_DEFAULT_JOIN_FAIL: input_process = input_process_joinfail; break; case MMP_SERVER_CLOSE: input_process = input_process_close; break; case MMP_SERVER_DEFAULT_SHIPADD_CLIENT: @; break; case MMP_SERVER_DEFAULT_SHIPADD_OTHER: @; break; case MMP_SERVER_DEFAULT_FRAME_SHIPS: input_process = input_process_number; input_process_done = input_process_frame_ships; input_number = 0; input_number_bytes = 2; break; case MMP_SERVER_DEFAULT_SHIPRM: @; break; default: fprintf(stderr, "Unknown message: [msg:%d][state:Default]\n", c); exit(EXIT_FAILURE); } } @ @= { input_process = input_process_number; input_process_done = input_process_shiprm_un; input_number = 0; input_number_bytes = 2; } @ @= void input_process_shiprm_un ( void ) { input_process = input_process_string; input_process_done = input_process_shiprm_name; input_string = NULL; input_string_len = 0; input_string_siz = 0; } @ @= void input_process_shiprm_name ( void ) { input_process = input_process_default; VERBOSE("Remove ship: %s\n", input_string); REMOVE_SHIP(input_string); free(input_string); } @ @= { input_number = 0; input_number_bytes = 2; input_process = input_process_number; input_process_done = input_process_shipadd_other_un; } @ @= void input_process_shipadd_other_un ( void ) { ASSERT(input_number == 0); input_string = NULL; input_string_len = 0; input_string_siz = 0; input_process = input_process_string; input_process_done = input_process_shipadd_other_name; } @ @= void input_process_shipadd_other_name ( void ) { ASSERT(input_string); REGISTER_SHIP_HEAD(input_string); VERBOSE("Adding ship: %s\n", input_string); input_process = input_process_default; } @ @= { static int current = 0; char *buffer; buffer = malloc(9); if (!buffer) { fprintf(stderr, "%s: malloc: %s\n", program_name, strerror(errno)); exit(EXIT_FAILURE); } sprintf(buffer, "AI%d", current ++); printf("Added a ship to the universe.\n"); REGISTER_SHIP_HEAD(strdup(buffer)); } @ Now a function to read numbers. @= void input_process_number ( unsigned int c ) { ASSERT(input_number_bytes > 0); ASSERT(0 <= c); ASSERT( c <= 255); input_number = input_number * 255 + c; if (input_number_bytes == 1) input_process_done(); else input_number_bytes --; } @ A function to read information about a ship's state. @= void input_process_frame_ships ( void ) { if (!mat_universe->ship_list_head) input_process = input_process_frame; else { input_process = input_process_number; input_process_done = input_process_frame_ships_x; input_number = 0; input_number_bytes = 2; mat_universe->ship_read = mat_universe->ship_list_head; } } @ @= void input_process_frame_ships_x ( void ) { mat_universe->ship_read->pos_x[mat_universe->read] = input_number; input_process = input_process_number; input_process_done = input_process_frame_ships_y; input_number = 0; input_number_bytes = 2; } @ @= void input_process_frame_ships_y ( void ) { mat_universe->ship_read->pos_y[mat_universe->read] = input_number; input_process = input_process_number; input_process_done = input_process_frame_ships_ang; input_number = 0; input_number_bytes = 2; } @ @= void input_process_frame_ships_ang ( void ) { mat_universe->ship_read->ang[mat_universe->read] = input_number; VERBOSE("[x:%d][y:%d][ang:%d]\n", mat_universe->ship_read->pos_x[mat_universe->read], mat_universe->ship_read->pos_y[mat_universe->read], mat_universe->ship_read->ang[mat_universe->read]); if (!mat_universe->ship_read->next) { VERBOSE("Done\n"); input_process = input_process_frame; } else { input_process = input_process_number; input_process_done = input_process_frame_ships_x; input_number = 0; input_number_bytes = 2; mat_universe->ship_read = mat_universe->ship_read->next; } } @ @= void input_process_frame ( unsigned int c ) { switch (c) { case MMP_SERVER_FRAME_DONE: input_process = input_process_default; break; default: fprintf(stderr, "Unknown message: [msg:%d][state:Frame]\n", c); exit(EXIT_FAILURE); } } @ This gets executed once the client gets to join a universe. It adds as many ships as specified by |ai_arg_concurrent|. @= { input_string = NULL; input_string_len = 0; input_string_siz = 0; @; input_process = input_process_string; input_process_done = input_process_shipname; } @ @= { int i; mat_universe = malloc(sizeof(MatUniverse)); if (!mat_universe) { fprintf(stderr, "%s: malloc: %s\n", program_name, strerror(errno)); exit(EXIT_FAILURE); } for (i = 0; i < MAT_SHIP_HASH_SIZE; i ++) mat_universe->ship_hash[i] = NULL; mat_universe->read = 0; mat_universe->ship_list_head = NULL; mat_universe->ship_list_tail = NULL; mat_universe->size_x = 1200; mat_universe->size_y = 1000; } @ @= void input_process_shipname ( void ) { if (!input_string || !*input_string) @@; else { REGISTER_SHIP_TAIL(input_string); input_string = NULL; input_string_len = 0; input_string_siz = 0; input_process = input_process_string; input_process_done = input_process_shipname; } } @ When this code gets executed, the name of a ship in the universe is in input_string. We register it. @d REGISTER_SHIP_TAIL(xname) { MatShip *ship; int pos; REGISTER_SHIP_STANDARD(xname); ship->ship->next = NULL; ship->ship->prev = mat_universe->ship_list_tail; if (mat_universe->ship_list_tail) mat_universe->ship_list_tail->next = ship->ship; else mat_universe->ship_list_head = ship->ship; mat_universe->ship_list_tail = ship->ship; } @d REGISTER_SHIP_HEAD(xname) { MatShip *ship; int pos; REGISTER_SHIP_STANDARD(xname); ship->ship->next = mat_universe->ship_list_head; ship->ship->prev = NULL; if (mat_universe->ship_list_head) mat_universe->ship_list_head->prev = ship->ship; else mat_universe->ship_list_tail = ship->ship; mat_universe->ship_list_head = ship->ship; } @d REGISTER_SHIP_STANDARD(xname) { ship = malloc(sizeof(MatShip)); if (!ship) { fprintf(stderr, "%s: malloc: %s\n", program_name, strerror(errno)); exit(EXIT_FAILURE); } ship->name = xname; ship->ship = malloc(sizeof(MatMovingObj)); if (!ship->ship) { fprintf(stderr, "%s: malloc: %s\n", program_name, strerror(errno)); exit(EXIT_FAILURE); } pos = fhash(ship->name) % MAT_SHIP_HASH_SIZE; ship->next = mat_universe->ship_hash[pos]; mat_universe->ship_hash[pos] = ship; } @d REMOVE_SHIP(xname) { MatShip *ship; int pos; pos = fhash(xname) % MAT_SHIP_HASH_SIZE; ship = mat_universe->ship_hash[pos]; ASSERT(ship); if (!strcmp(ship->name, xname)) mat_universe->ship_hash[pos] = ship->next; else { MatShip *tmp; ASSERT(ship->next); while (strcmp(ship->next->name, xname)) { ship = ship->next; ASSERT(ship->next); ASSERT(ship->next->name); } tmp = ship->next; ship->next = ship->next->next; ship = tmp; } if (ship->ship->prev) ship->ship->prev->next = ship->ship->next; else mat_universe->ship_list_head = ship->ship->next; if (ship->ship->next) ship->ship->next->prev = ship->ship->prev; else mat_universe->ship_list_tail = ship->ship->prev; free(ship->ship); free(ship->name); free(ship); } @ @= { input_process = input_process_default; printf("Successfully joined default universe.\n"); fprintf(mat_server_out, "%c%c%c%s%c", MMP_CLIENT_DEFAULT_SHIPADD, 0, 0, "AICode", 0); fflush(mat_server_out); } @ @= void input_process_joinfail ( unsigned int c ) { switch (c) { case MMP_SERVER_JOINFAIL_UNEXISTANT: fprintf(stderr, "%s: Default universe not available\n", program_name); break; default: fprintf(stderr, "Unknown message: [msg:%d][state:JoinFail]\n", c); break; } exit(EXIT_FAILURE); } @ Here we read all the information available on how the world has changed. @= { int read; while ((read = getc(mat_server_in)) != EOF) { /*VERBOSE("Got: %d (%c)\n", read, read);*/ input_process((unsigned int) read); } } @* Program Initialization In this section we will write all the code that initializes the Matanza Aritificial Inteligence system. @= { @; @; @; @; } @ Here we set the global variable |program_name|. It is used across the program at the beginning of all the error messages. If the program name contains slashes, we discard everything before the last of them. @= { program_name = strrchr(argv[0], '/'); if (program_name) program_name++; else program_name = argv[0]; } @ @= { } @ @= char *arg_host = "localhost"; int arg_port = 7793; char *arg_src = NULL; @ @= { int iterate = 1; int show_help = 0; int show_version = 0; while (iterate) { int oi = 0; static struct option lopt[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'v' }, { "host", required_argument, NULL, 1 }, { "port", required_argument, NULL, 2 }, { 0, 0, 0, 0 } }; switch (getopt_long(argc, argv, "hvm:bW:H:x:y:l:A:t:p::", lopt, &oi)) { case -1: iterate = 0; break; case 'h': show_help = 1; break; case 'v': show_version = 1; break; case 1: arg_host = optarg; break; case 2: arg_port = atoi(optarg); break; default: printf("Try '%s --help' for more information.\n", program_name); exit(EXIT_FAILURE); } } if (show_help) { printf("Usage: %s [OPTION]... [FILE]\n" "Execute a Matanza Artificial Inteligence from FILE\n\n" " -h, --help Show this information and exit\n" " -v, --version Show version number and exit\n" " --host=HOST Connect to HOST\n" " --port=NUM Use TCP port NUM\n" "\n" "Report bugs to \n", program_name); exit(EXIT_SUCCESS); /* TODO: List parameter ai!!! */ } if (show_version) { printf("Freaks Unidos' %s %s\n" "Copyright (C) 2000 Alejandro Forero Cuervo\n" "Report any bugs to \n" "Check for updates\n", PACKAGE, VERSION); exit(EXIT_SUCCESS); } } @ Here we perform the DNS and port lookup and attempt to connect to all known addresses for the server specified. @= { struct sockaddr_in addr; struct hostent *host = NULL; int i = 0; int fd; @; /* Get a socket file descriptor. */ fd = socket(AF_INET, SOCK_STREAM, 0); if (fd < 0) { fprintf(stderr, "%s: socket: %s\n", program_name, strerror(errno)); exit(EXIT_FAILURE); } /* Connect to the server. */ while (connect(fd, &addr, sizeof(struct sockaddr_in)) == -1) if (errno != EINTR) { if (!host || !host->h_addr_list[++i]) { fprintf(stderr, "%s: %s: %s\n", program_name, arg_host, strerror(errno)); exit(EXIT_FAILURE); } memmove((caddr_t)&addr.sin_addr, host->h_addr_list[i], host->h_length); } @; @; @; } @ @= { fprintf(mat_server_out, "%c%s%c%s%c", MMP_CLIENT_INITIAL_ID, PACKAGE " - Artificial Inteligence System", 0, VERSION, 0); fflush(mat_server_out); } @ Here we make it so reads and writes to the socket won't block the process. @= { int opts; opts = fcntl(fd, F_GETFL); if (opts < 0) { fprintf(stderr, "%s: fcntl: %s\n", program_name, strerror(errno)); exit(EXIT_FAILURE); } opts = (opts | O_NONBLOCK); if (fcntl(fd, F_SETFL, opts) < 0) { fprintf(stderr, "%s: fcntl: %s\n", program_name, strerror(errno)); exit(EXIT_FAILURE); } } @ This one calls |fdopen| on |fd| to open |mat_server_in| and |mat_server_out|. @= { mat_server_in = fdopen(fd, "r"); if (!mat_server_in) { fprintf(stderr, "%s: %s\n", program_name, strerror(errno)); exit(EXIT_FAILURE); } mat_server_out = fdopen(fd, "w"); if (!mat_server_out) { fprintf(stderr, "%s: %s\n", program_name, strerror(errno)); exit(EXIT_FAILURE); } } @ @= { /* Initialize the sockaddr_in structure. */ memset(&addr, 0, sizeof(struct sockaddr_in)); addr.sin_addr.s_addr = inet_addr(arg_host); if (addr.sin_addr.s_addr != -1) addr.sin_family = AF_INET; else { host = gethostbyname(arg_host); if (!host) { #if HAVE_HSTRERROR fprintf(stderr, "%s: %s: %s\n", program_name, arg_host, hstrerror(errno)); #else fprintf(stderr, "%s: %s: Host not found\n", program_name, arg_host); #endif exit(EXIT_FAILURE); } addr.sin_family = host->h_addrtype; memmove((caddr_t)&addr.sin_addr, host->h_addr_list[0], host->h_length); } addr.sin_port = htons(arg_port); } @* State of the Program In this section we will add information used to represent the state of the world in memory. @ First, lets define a structure we can use to keep a record of the ships in a universe. @= typedef struct MatShip MatShip; @ Lets see the fields for every |MatShip| object. We will need to keep the name of the ship in the |name field|. In MMP, we receive information about the state of every ship individually, and they are identified by their name. That means we need to have fast access to every ship identified by the name. We will keep a hash with every player. |next| will hold a pointer to the next node in the current list in the hash. Finally, rather than keep the whole information about the ship here, we use the struct |MatMovingObj|. @= struct MatShip { char *name; MatMovingObj *ship; MatShip *next; }; @ We spoke about |MatMovingObj| so we better define it. It will keep all the information sent through MMP about all the moving objects. @= typedef struct MatMovingObj MatMovingObj; @ In every MatMovingObj we keep the information about a single object in the universe. The fields |pos_x| and |pos_y| contain the object's coordinates. The current angle of the object is kept in |ang|. As you can see, for both |pos_x|, |pos_y| and |ang|, we use an array with two possible values. The field |read| in this objects' universe indicates on which field we are reading from the network, and the other is the one that gets used during AI's execution. @= struct MatMovingObj { int pos_x[2]; int pos_y[2]; int ang[2]; MatMovingObj *next; MatMovingObj *prev; }; @ Lets now define the information we keep for every universe. @= typedef struct MatUniverse MatUniverse; @ Fields |size_x| and |size_y| hold the size of the universe. In |ship_hash| we keep a hash with all the players so they can be easily accessed by their name. |ship_list| is the list of all the players, so it's fast to paint them all. |ship_read| points to the ship currently being read from the network. We store a count of the number of frames received in |frames|. @d MAT_SHIP_HASH_SIZE 47 @= struct MatUniverse { int size_x, size_y; int read; unsigned long frames; MatMovingObj *ship_read; MatShip *ship_hash[MAT_SHIP_HASH_SIZE]; MatMovingObj *ship_list_head; MatMovingObj *ship_list_tail; }; @ @= MatUniverse *mat_universe = NULL; @* AI Related stuff @= typedef struct AIInstruction AIInstruction; @ @= struct AIInstruction { int code; int arg1; int arg2; int arg3; AIInstruction *next; }; @ @d AI_INST_STORE 0 @= { AIInstruction *in; in = ai_program[ai_current]; switch (in->code) { /* mem[arg2] = arg1 */ case 1: ai_hash_set(in->arg2, in->arg1); break; /* mem[arg2] = mem[arg1] */ case 2: ai_hash_set(in->arg2, ai_hash_get(in->arg1)); break; /* mem[mem[arg2]] = arg1 */ case 4: ai_hash_set(ai_hash_get(in->arg2), in->arg1); break; /* mem[mem[arg2]] = mem[arg1] */ case 3: ai_hash_set(ai_hash_get(in->arg2), ai_hash_get(in->arg1)); break; /* mem[arg2] = screen[arg1 x arg2] */ case 4: if (in->arg1 > ai_hash_set(in->arg2, ai_hash_get(in } } @ @= { } @ @= { } @ Lets include all the files we can. We should check this and make sure it really is what we want. @= #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include @ Now some mechanisms for assertions. @d ASSERT(x) if(!(x)) fprintf(stderr, "%s:%d: ASSERT failed\n", __FILE__, __LINE__), assert_exit() @d ASSERT_FOR(x) for (x) @= void assert_exit ( void ); @ The function assert_exit is used so you can have your debugger stop execution when an assertion fails. @= void assert_exit ( void ) { exit(-1); } @ Define |VERBOSE| to empty to get rid of the messages. @d VERBOSE printf @ @= #ifdef HAVE_CONFIG_H #include #else #define PACKAGE "matanza" #define VERSION "{Unknown-Version}" #endif @ #if ! HAVE_HSTRERROR # define hsterror(x) "Host not found" #endif matanza-0.13/xmlparse.h0000644000175000017500000004704407254521711015261 0ustar boradminboradmin/* Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd See the file copying.txt for copying permission. */ #ifndef XmlParse_INCLUDED #define XmlParse_INCLUDED 1 #ifdef __cplusplus extern "C" { #endif #ifndef XMLPARSEAPI #define XMLPARSEAPI /* as nothing */ #endif typedef void *XML_Parser; #ifdef XML_UNICODE_WCHAR_T /* XML_UNICODE_WCHAR_T will work only if sizeof(wchar_t) == 2 and wchar_t uses Unicode. */ /* Information is UTF-16 encoded as wchar_ts */ #ifndef XML_UNICODE #define XML_UNICODE #endif #include typedef wchar_t XML_Char; typedef wchar_t XML_LChar; #else /* not XML_UNICODE_WCHAR_T */ #ifdef XML_UNICODE /* Information is UTF-16 encoded as unsigned shorts */ typedef unsigned short XML_Char; typedef char XML_LChar; #else /* not XML_UNICODE */ /* Information is UTF-8 encoded. */ typedef char XML_Char; typedef char XML_LChar; #endif /* not XML_UNICODE */ #endif /* not XML_UNICODE_WCHAR_T */ /* Constructs a new parser; encoding is the encoding specified by the external protocol or null if there is none specified. */ XML_Parser XMLPARSEAPI XML_ParserCreate(const XML_Char *encoding); /* Constructs a new parser and namespace processor. Element type names and attribute names that belong to a namespace will be expanded; unprefixed attribute names are never expanded; unprefixed element type names are expanded only if there is a default namespace. The expanded name is the concatenation of the namespace URI, the namespace separator character, and the local part of the name. If the namespace separator is '\0' then the namespace URI and the local part will be concatenated without any separator. When a namespace is not declared, the name and prefix will be passed through without expansion. */ XML_Parser XMLPARSEAPI XML_ParserCreateNS(const XML_Char *encoding, XML_Char namespaceSeparator); /* atts is array of name/value pairs, terminated by 0; names and values are 0 terminated. */ typedef void (*XML_StartElementHandler)(void *userData, const XML_Char *name, const XML_Char **atts); typedef void (*XML_EndElementHandler)(void *userData, const XML_Char *name); /* s is not 0 terminated. */ typedef void (*XML_CharacterDataHandler)(void *userData, const XML_Char *s, int len); /* target and data are 0 terminated */ typedef void (*XML_ProcessingInstructionHandler)(void *userData, const XML_Char *target, const XML_Char *data); /* data is 0 terminated */ typedef void (*XML_CommentHandler)(void *userData, const XML_Char *data); typedef void (*XML_StartCdataSectionHandler)(void *userData); typedef void (*XML_EndCdataSectionHandler)(void *userData); /* This is called for any characters in the XML document for which there is no applicable handler. This includes both characters that are part of markup which is of a kind that is not reported (comments, markup declarations), or characters that are part of a construct which could be reported but for which no handler has been supplied. The characters are passed exactly as they were in the XML document except that they will be encoded in UTF-8. Line boundaries are not normalized. Note that a byte order mark character is not passed to the default handler. There are no guarantees about how characters are divided between calls to the default handler: for example, a comment might be split between multiple calls. */ typedef void (*XML_DefaultHandler)(void *userData, const XML_Char *s, int len); /* This is called for the start of the DOCTYPE declaration when the name of the DOCTYPE is encountered. */ typedef void (*XML_StartDoctypeDeclHandler)(void *userData, const XML_Char *doctypeName); /* This is called for the start of the DOCTYPE declaration when the closing > is encountered, but after processing any external subset. */ typedef void (*XML_EndDoctypeDeclHandler)(void *userData); /* This is called for a declaration of an unparsed (NDATA) entity. The base argument is whatever was set by XML_SetBase. The entityName, systemId and notationName arguments will never be null. The other arguments may be. */ typedef void (*XML_UnparsedEntityDeclHandler)(void *userData, const XML_Char *entityName, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId, const XML_Char *notationName); /* This is called for a declaration of notation. The base argument is whatever was set by XML_SetBase. The notationName will never be null. The other arguments can be. */ typedef void (*XML_NotationDeclHandler)(void *userData, const XML_Char *notationName, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId); typedef void (*XML_ExternalParsedEntityDeclHandler)(void *userData, const XML_Char *entityName, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId); typedef void (*XML_InternalParsedEntityDeclHandler)(void *userData, const XML_Char *entityName, const XML_Char *replacementText, int replacementTextLength); /* When namespace processing is enabled, these are called once for each namespace declaration. The call to the start and end element handlers occur between the calls to the start and end namespace declaration handlers. For an xmlns attribute, prefix will be null. For an xmlns="" attribute, uri will be null. */ typedef void (*XML_StartNamespaceDeclHandler)(void *userData, const XML_Char *prefix, const XML_Char *uri); typedef void (*XML_EndNamespaceDeclHandler)(void *userData, const XML_Char *prefix); /* This is called if the document is not standalone (it has an external subset or a reference to a parameter entity, but does not have standalone="yes"). If this handler returns 0, then processing will not continue, and the parser will return a XML_ERROR_NOT_STANDALONE error. */ typedef int (*XML_NotStandaloneHandler)(void *userData); /* This is called for a reference to an external parsed general entity. The referenced entity is not automatically parsed. The application can parse it immediately or later using XML_ExternalEntityParserCreate. The parser argument is the parser parsing the entity containing the reference; it can be passed as the parser argument to XML_ExternalEntityParserCreate. The systemId argument is the system identifier as specified in the entity declaration; it will not be null. The base argument is the system identifier that should be used as the base for resolving systemId if systemId was relative; this is set by XML_SetBase; it may be null. The publicId argument is the public identifier as specified in the entity declaration, or null if none was specified; the whitespace in the public identifier will have been normalized as required by the XML spec. The context argument specifies the parsing context in the format expected by the context argument to XML_ExternalEntityParserCreate; context is valid only until the handler returns, so if the referenced entity is to be parsed later, it must be copied. The handler should return 0 if processing should not continue because of a fatal error in the handling of the external entity. In this case the calling parser will return an XML_ERROR_EXTERNAL_ENTITY_HANDLING error. Note that unlike other handlers the first argument is the parser, not userData. */ typedef int (*XML_ExternalEntityRefHandler)(XML_Parser parser, const XML_Char *context, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId); /* This structure is filled in by the XML_UnknownEncodingHandler to provide information to the parser about encodings that are unknown to the parser. The map[b] member gives information about byte sequences whose first byte is b. If map[b] is c where c is >= 0, then b by itself encodes the Unicode scalar value c. If map[b] is -1, then the byte sequence is malformed. If map[b] is -n, where n >= 2, then b is the first byte of an n-byte sequence that encodes a single Unicode scalar value. The data member will be passed as the first argument to the convert function. The convert function is used to convert multibyte sequences; s will point to a n-byte sequence where map[(unsigned char)*s] == -n. The convert function must return the Unicode scalar value represented by this byte sequence or -1 if the byte sequence is malformed. The convert function may be null if the encoding is a single-byte encoding, that is if map[b] >= -1 for all bytes b. When the parser is finished with the encoding, then if release is not null, it will call release passing it the data member; once release has been called, the convert function will not be called again. Expat places certain restrictions on the encodings that are supported using this mechanism. 1. Every ASCII character that can appear in a well-formed XML document, other than the characters $@\^`{}~ must be represented by a single byte, and that byte must be the same byte that represents that character in ASCII. 2. No character may require more than 4 bytes to encode. 3. All characters encoded must have Unicode scalar values <= 0xFFFF, (ie characters that would be encoded by surrogates in UTF-16 are not allowed). Note that this restriction doesn't apply to the built-in support for UTF-8 and UTF-16. 4. No Unicode character may be encoded by more than one distinct sequence of bytes. */ typedef struct { int map[256]; void *data; int (*convert)(void *data, const char *s); void (*release)(void *data); } XML_Encoding; /* This is called for an encoding that is unknown to the parser. The encodingHandlerData argument is that which was passed as the second argument to XML_SetUnknownEncodingHandler. The name argument gives the name of the encoding as specified in the encoding declaration. If the callback can provide information about the encoding, it must fill in the XML_Encoding structure, and return 1. Otherwise it must return 0. If info does not describe a suitable encoding, then the parser will return an XML_UNKNOWN_ENCODING error. */ typedef int (*XML_UnknownEncodingHandler)(void *encodingHandlerData, const XML_Char *name, XML_Encoding *info); void XMLPARSEAPI XML_SetElementHandler(XML_Parser parser, XML_StartElementHandler start, XML_EndElementHandler end); void XMLPARSEAPI XML_SetCharacterDataHandler(XML_Parser parser, XML_CharacterDataHandler handler); void XMLPARSEAPI XML_SetProcessingInstructionHandler(XML_Parser parser, XML_ProcessingInstructionHandler handler); void XMLPARSEAPI XML_SetCommentHandler(XML_Parser parser, XML_CommentHandler handler); void XMLPARSEAPI XML_SetCdataSectionHandler(XML_Parser parser, XML_StartCdataSectionHandler start, XML_EndCdataSectionHandler end); /* This sets the default handler and also inhibits expansion of internal entities. The entity reference will be passed to the default handler. */ void XMLPARSEAPI XML_SetDefaultHandler(XML_Parser parser, XML_DefaultHandler handler); /* This sets the default handler but does not inhibit expansion of internal entities. The entity reference will not be passed to the default handler. */ void XMLPARSEAPI XML_SetDefaultHandlerExpand(XML_Parser parser, XML_DefaultHandler handler); void XMLPARSEAPI XML_SetDoctypeDeclHandler(XML_Parser parser, XML_StartDoctypeDeclHandler start, XML_EndDoctypeDeclHandler end); void XMLPARSEAPI XML_SetUnparsedEntityDeclHandler(XML_Parser parser, XML_UnparsedEntityDeclHandler handler); void XMLPARSEAPI XML_SetNotationDeclHandler(XML_Parser parser, XML_NotationDeclHandler handler); void XMLPARSEAPI XML_SetExternalParsedEntityDeclHandler(XML_Parser parser, XML_ExternalParsedEntityDeclHandler handler); void XMLPARSEAPI XML_SetInternalParsedEntityDeclHandler(XML_Parser parser, XML_InternalParsedEntityDeclHandler handler); void XMLPARSEAPI XML_SetNamespaceDeclHandler(XML_Parser parser, XML_StartNamespaceDeclHandler start, XML_EndNamespaceDeclHandler end); void XMLPARSEAPI XML_SetNotStandaloneHandler(XML_Parser parser, XML_NotStandaloneHandler handler); void XMLPARSEAPI XML_SetExternalEntityRefHandler(XML_Parser parser, XML_ExternalEntityRefHandler handler); /* If a non-null value for arg is specified here, then it will be passed as the first argument to the external entity ref handler instead of the parser object. */ void XMLPARSEAPI XML_SetExternalEntityRefHandlerArg(XML_Parser, void *arg); void XMLPARSEAPI XML_SetUnknownEncodingHandler(XML_Parser parser, XML_UnknownEncodingHandler handler, void *encodingHandlerData); /* This can be called within a handler for a start element, end element, processing instruction or character data. It causes the corresponding markup to be passed to the default handler. */ void XMLPARSEAPI XML_DefaultCurrent(XML_Parser parser); /* This value is passed as the userData argument to callbacks. */ void XMLPARSEAPI XML_SetUserData(XML_Parser parser, void *userData); /* Returns the last value set by XML_SetUserData or null. */ #define XML_GetUserData(parser) (*(void **)(parser)) /* This is equivalent to supplying an encoding argument to XML_ParserCreate. It must not be called after XML_Parse or XML_ParseBuffer. */ int XMLPARSEAPI XML_SetEncoding(XML_Parser parser, const XML_Char *encoding); /* If this function is called, then the parser will be passed as the first argument to callbacks instead of userData. The userData will still be accessible using XML_GetUserData. */ void XMLPARSEAPI XML_UseParserAsHandlerArg(XML_Parser parser); /* Sets the base to be used for resolving relative URIs in system identifiers in declarations. Resolving relative identifiers is left to the application: this value will be passed through as the base argument to the XML_ExternalEntityRefHandler, XML_NotationDeclHandler and XML_UnparsedEntityDeclHandler. The base argument will be copied. Returns zero if out of memory, non-zero otherwise. */ int XMLPARSEAPI XML_SetBase(XML_Parser parser, const XML_Char *base); const XML_Char XMLPARSEAPI * XML_GetBase(XML_Parser parser); /* Returns the number of the attribute/value pairs passed in last call to the XML_StartElementHandler that were specified in the start-tag rather than defaulted. Each attribute/value pair counts as 2; thus this correspondds to an index into the atts array passed to the XML_StartElementHandler. */ int XMLPARSEAPI XML_GetSpecifiedAttributeCount(XML_Parser parser); /* Returns the index of the ID attribute passed in the last call to XML_StartElementHandler, or -1 if there is no ID attribute. Each attribute/value pair counts as 2; thus this correspondds to an index into the atts array passed to the XML_StartElementHandler. */ int XMLPARSEAPI XML_GetIdAttributeIndex(XML_Parser parser); /* Parses some input. Returns 0 if a fatal error is detected. The last call to XML_Parse must have isFinal true; len may be zero for this call (or any other). */ int XMLPARSEAPI XML_Parse(XML_Parser parser, const char *s, int len, int isFinal); void XMLPARSEAPI * XML_GetBuffer(XML_Parser parser, int len); int XMLPARSEAPI XML_ParseBuffer(XML_Parser parser, int len, int isFinal); /* Creates an XML_Parser object that can parse an external general entity; context is a '\0'-terminated string specifying the parse context; encoding is a '\0'-terminated string giving the name of the externally specified encoding, or null if there is no externally specified encoding. The context string consists of a sequence of tokens separated by formfeeds (\f); a token consisting of a name specifies that the general entity of the name is open; a token of the form prefix=uri specifies the namespace for a particular prefix; a token of the form =uri specifies the default namespace. This can be called at any point after the first call to an ExternalEntityRefHandler so longer as the parser has not yet been freed. The new parser is completely independent and may safely be used in a separate thread. The handlers and userData are initialized from the parser argument. Returns 0 if out of memory. Otherwise returns a new XML_Parser object. */ XML_Parser XMLPARSEAPI XML_ExternalEntityParserCreate(XML_Parser parser, const XML_Char *context, const XML_Char *encoding); enum XML_ParamEntityParsing { XML_PARAM_ENTITY_PARSING_NEVER, XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE, XML_PARAM_ENTITY_PARSING_ALWAYS }; /* Controls parsing of parameter entities (including the external DTD subset). If parsing of parameter entities is enabled, then references to external parameter entities (including the external DTD subset) will be passed to the handler set with XML_SetExternalEntityRefHandler. The context passed will be 0. Unlike external general entities, external parameter entities can only be parsed synchronously. If the external parameter entity is to be parsed, it must be parsed during the call to the external entity ref handler: the complete sequence of XML_ExternalEntityParserCreate, XML_Parse/XML_ParseBuffer and XML_ParserFree calls must be made during this call. After XML_ExternalEntityParserCreate has been called to create the parser for the external parameter entity (context must be 0 for this call), it is illegal to make any calls on the old parser until XML_ParserFree has been called on the newly created parser. If the library has been compiled without support for parameter entity parsing (ie without XML_DTD being defined), then XML_SetParamEntityParsing will return 0 if parsing of parameter entities is requested; otherwise it will return non-zero. */ int XMLPARSEAPI XML_SetParamEntityParsing(XML_Parser parser, enum XML_ParamEntityParsing parsing); enum XML_Error { XML_ERROR_NONE, XML_ERROR_NO_MEMORY, XML_ERROR_SYNTAX, XML_ERROR_NO_ELEMENTS, XML_ERROR_INVALID_TOKEN, XML_ERROR_UNCLOSED_TOKEN, XML_ERROR_PARTIAL_CHAR, XML_ERROR_TAG_MISMATCH, XML_ERROR_DUPLICATE_ATTRIBUTE, XML_ERROR_JUNK_AFTER_DOC_ELEMENT, XML_ERROR_PARAM_ENTITY_REF, XML_ERROR_UNDEFINED_ENTITY, XML_ERROR_RECURSIVE_ENTITY_REF, XML_ERROR_ASYNC_ENTITY, XML_ERROR_BAD_CHAR_REF, XML_ERROR_BINARY_ENTITY_REF, XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF, XML_ERROR_MISPLACED_XML_PI, XML_ERROR_UNKNOWN_ENCODING, XML_ERROR_INCORRECT_ENCODING, XML_ERROR_UNCLOSED_CDATA_SECTION, XML_ERROR_EXTERNAL_ENTITY_HANDLING, XML_ERROR_NOT_STANDALONE }; /* If XML_Parse or XML_ParseBuffer have returned 0, then XML_GetErrorCode returns information about the error. */ enum XML_Error XMLPARSEAPI XML_GetErrorCode(XML_Parser parser); /* These functions return information about the current parse location. They may be called when XML_Parse or XML_ParseBuffer return 0; in this case the location is the location of the character at which the error was detected. They may also be called from any other callback called to report some parse event; in this the location is the location of the first of the sequence of characters that generated the event. */ int XMLPARSEAPI XML_GetCurrentLineNumber(XML_Parser parser); int XMLPARSEAPI XML_GetCurrentColumnNumber(XML_Parser parser); long XMLPARSEAPI XML_GetCurrentByteIndex(XML_Parser parser); /* Return the number of bytes in the current event. Returns 0 if the event is in an internal entity. */ int XMLPARSEAPI XML_GetCurrentByteCount(XML_Parser parser); /* For backwards compatibility with previous versions. */ #define XML_GetErrorLineNumber XML_GetCurrentLineNumber #define XML_GetErrorColumnNumber XML_GetCurrentColumnNumber #define XML_GetErrorByteIndex XML_GetCurrentByteIndex /* Frees memory used by the parser. */ void XMLPARSEAPI XML_ParserFree(XML_Parser parser); /* Returns a string describing the error. */ const XML_LChar XMLPARSEAPI *XML_ErrorString(int code); #ifdef __cplusplus } #endif #endif /* not XmlParse_INCLUDED */ matanza-0.13/ship.txt0000644000175000017500000001135207255771513014762 0ustar boradminboradmin# This graphic must be 116 x 54 characters big. If you modify it and come # up with anything interesting, send it to so it gets # included with the next release. We are planning to distribute a big list # of ships and allow the players to choose from among them. # # For the moment, you must make sure the sizes and positions of the # missiles does -not- change. In the future, you'll be able to place them # anywhere. # # Lines begining with `#' get ignored. # # To try your new image, use the `--ship-img' argument when you run Matanza # (for example: matanza --ship-img ship.txt). # # By the way, to edit this file under Vim, you'll want to use :set nowrap # to have it not perform line wrapping. XX XX XX XX XX XX XXXX XXXXXXXX *XXXXXXXXXX* *XXXXXXXXXX* **XXXXXXXXXX** **XXXXXXXXXX** **XXXX..XXXX** ***XXX....XXX*** ****XX......XX**** *****XX......XX***** ******X........X****** *******X........X******* 1 ********X........X******** 2 1 *********X........X********* 2 1 **********X........X********** 2 111 ***********X........X*********** 222 111 ************XX......XX************ 222 111 *************XXX....XXX************* 222 111 **************XXXX..XXXX************** 222 111 ***************XXXXXXXXXX*************** 222 111 ****************XXXXXXXXXX**************** 222 111 *****************XXXXXXXXXX***************** 222 111 ******************XXXXXXXXXX****************** 222 111 *******************XXXXXXXXXX******************* 222 111********************XXXXXXXXXX********************222 11*********************XXXXXXXXXX*********************22 1**********************XXXXXXXXXX**********************2 ***********************XXXXXXXXXX*********************** ************************XXXXXXXXXX************************ *************************XXXXXXXXXX************************* **************************XXXXXXXXXX************************** ***************************XXXXXXXXXX*************************** ***************************XXXXXXXXXX*************************** ************ **XXXXXXXXXX** ************ ******** XXXXXXXX ******** *******11 XXXXXX 22******* **** 111 XXXXXX 222 **** ** 111 XXXXXX 222 ** * 111 XXXXXX 222 * 111 XXXXXX 222 111 XXXX 222 111 XXXX 222 111 *XXXX* 222 1 ***XXXX*** 2 ********XXXX******** XX matanza-0.13/latin1tab.h0000644000175000017500000000342607254453527015312 0ustar boradminboradmin/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd See the file copying.txt for copying permission. */ /* 0x80 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, /* 0x84 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, /* 0x88 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, /* 0x8C */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, /* 0x90 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, /* 0x94 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, /* 0x98 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, /* 0x9C */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, /* 0xA0 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, /* 0xA4 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, /* 0xA8 */ BT_OTHER, BT_OTHER, BT_NMSTRT, BT_OTHER, /* 0xAC */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, /* 0xB0 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, /* 0xB4 */ BT_OTHER, BT_NMSTRT, BT_OTHER, BT_NAME, /* 0xB8 */ BT_OTHER, BT_OTHER, BT_NMSTRT, BT_OTHER, /* 0xBC */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, /* 0xC0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0xC4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0xC8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0xCC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0xD0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0xD4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER, /* 0xD8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0xDC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0xE0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0xE4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0xE8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0xEC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0xF0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0xF4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER, /* 0xF8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0xFC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, matanza-0.13/matanza.w0000644000175000017500000113670307263246035015105 0ustar boradminboradmin@* Matanza - The Game. @c @ @ @ @ @ @ @ @ @* Struct definitions @d MY_STATE_WILL 0x01 @d MY_WANT_STATE_WILL 0x02 @d MY_STATE_DO 0x04 @d MY_WANT_STATE_DO 0x08 @= #define AA_NORMAL_MASK 1 /*masks for attributes */ #define AA_DIM_MASK 2 #define AA_BOLD_MASK 4 #define AA_BOLDFONT_MASK 8 #define AA_REVERSE_MASK 16 #define AA_ALL 128 #define AA_EIGHT 256 #define AA_EXTENDED (AA_ALL|AA_EIGHT) #define AA_ERRORDISTRIB 1 /*dithering types + AA_NONE */ #define AA_FLOYD_S 2 #define AA_DITHERTYPES 3 #define AA_NATTRS 5 #define AA_NPARAMS 5 struct parameters { unsigned int p[AA_NPARAMS]; }; typedef struct aa_font aa_font; struct aa_font { unsigned char *data; int height; char *name; char *shortname; }; struct aa_hardware_params { struct aa_font *font; int supported; int minwidth, minheight; int maxwidth, maxheight; int recwidth, recheight; int mmwidth, mmheight; int width, height; }; typedef struct MatTerm MatTerm; typedef struct MatLocation MatLocation; typedef struct MatTeam MatTeam; typedef struct MatShip MatShip; typedef struct MatMovingObj MatMovingObj; typedef struct MatImage MatImage; typedef struct MatUniverse MatUniverse; typedef struct MatConnection MatConnection; @ @ @ @ @ @ @ @ @ @ We need a struct to keep information about the terminals we support so it can be easily accessed. @= struct MatTerm { char *code [MAT_TERM_CODES]; int code_len[MAT_TERM_CODES]; char *cls; char *cursor_hide; char *cursor_show; char *cursor_pos; char *cursor_adv; }; @ @d MAXCHATBUFFERLEN 60 @d MAXMESSAGES 5 @d MAXMESSAGELEN 80 @d MAT_CONNECTION_SHIP_HASH_SIZE 13 @= struct MatConnection { MatSocketT fd; char *addr; /* Buffer for output. */ char *out_buf; int out_len; int out_siz; int state; MatMovingObj *ship_hash[MAT_CONNECTION_SHIP_HASH_SIZE]; MatMovingObj *ship_list; int ship_count; MatTerm *term; int xwinsize; int ywinsize; int graph_randomval; int graph_palette[256]; unsigned char *graph_imagebuffer; unsigned char *graph_textbuffer; unsigned char *graph_textbufferold; unsigned char *graph_attrbuffer; unsigned char *graph_attrbufferold; int graph_imgwidth; int graph_imgheight; struct aa_hardware_params params; /* has not been checked */ int flags; char terminal_name[14]; int telnet_args; int input_state; char *buffer; int bufsiz; int buflen; int bufprc; union { /* Here we keep information when this connection is for a machine. */ struct { int number; int number_byte; char *string; int string_len; int string_siz; int string_maxlength; void (*handler) ( MatConnection * ); MatSubMachine subs; } m; /* Here we keep information when this connection uses telnet. */ struct { int clean; } t; } info; void (*anim_func) (MatConnection *); void *anim_data; void (*key_handler) (MatConnection *, int); MatConnection *next; MatConnection *prev; }; @ |players_head| and |players_tail| hold a list with all the players. |players_real| is the number of players currently playing (in |MAT_STATE_PLAYING| state) in this universe. @d MAX_UNIVERSE_NAME 32 @d MAT_UNIVERSE_MAX 256 @= struct MatUniverse { int id; /* The next universe in the hash of universes. */ MatUniverse *next_hash; MatMovingObj *players_head; MatMovingObj *players_tail; int players_real; MatSub *subs; int updates; int crash_damage[3]; /* TODO: Comment out this field if no support for universes is included. */ char name[MAX_UNIVERSE_NAME]; char *path; MatMovingObj *bullets; MatMovingObj *smart_objs; MatMovingObj *ast; int ast_cur; int pause; /* Information for the different zones */ /* TODO: Comment out this field if no support for loading universes is included. */ MatLocation *location[256]; /* The initial health the ships have */ int health; /* The size of the map for this universe. */ int mapsize_x; int mapsize_y; /* Should we draw dots for this universe (background)? */ int dots; MatMovingObj *objs; /* Single linked list of all the objects (other than ships) in this universe * that should be removed as soon as possible. To traverse the list, follow * the |rm_next| field of every node. The last node in the list has * |rm_next| set to &main, not to NULL! * * Consult the documentation next ro |rm_next| in the |MatMovingObj| struct. * * Also, keep in mind that ships (objects of type |MAT_MOVING_OBJ_SHIP|) * should not be added to this list. */ MatMovingObj *objs_rm; MatImage *bg; MatImage *mask; }; struct MatLocation { /* Should the objects crash against this object? */ int crash[3]; /* How much damage does this object deal to the player on each turn? Usually * 0. Can be positive or negative. */ int health; /* Does being on this area slow the objects down? The movement of the objects * is multiplied with this value once for every turn. */ double move[3]; }; @ @= MatTerm term_vt100 = { { "\033[0;39m", "", "\033[1;39m", "\033[1;39m", "\033[0;7m", "\033[0;7m", "\033[0;31m", "\033[1;31m", "\033[0;34m" }, { 7, 0, 7, 7, 6, 6, 7, 7, 7 }, "\033[2J", "\033[?25l", "\033[?25h", "\033[%d;%dH", "\033[%dC" }; @ |MAT_TEAM_BLANK| must hold |MAT_TEAM_MAX| spaces. @d MAT_TEAM_MAX 8 @d MAT_TEAM_BLANK " " @= struct MatTeam { int max; int cur; int times_dead; char *name; MatMovingObj *head; MatTeam *next; MatTeam *prev; }; @ We keep one of this structs for every player. If you change |MAT_USER_MAX|, change |MAT_USER_BLANK|: It should hold |MAT_USER_MAX| spaces. |bullets| is the number of bullets the player has shot that are currently on the air. @d MAT_STATE_REMOVE 1 @d MAT_STATE_PREPARE 2 @d MAT_STATE_NORMAL 3 @d MAT_STATE_PLAYING 4 @d MAT_STATE_MACHINE 5 @d MAT_USER_MAX 8 @d MAT_USER_BLANK " " @= struct MatShip { char name[MAT_USER_MAX + 1]; @ MatTeam *team; MatMovingObj *team_next; int health; int visible; int visible_exp; int bullets_expire; int ship_bullets[4]; int ship_speed_inc; char chat_buffer[MAXCHATBUFFERLEN + 1]; int chat_buffer_len; int times_dead; /* game_over is evaluated to know if the player lost. */ int game_over; int messages_count; int messages_start; char messages[MAXMESSAGES][MAXMESSAGELEN]; int messages_expire[MAXMESSAGES]; int messages_pos; int messages_enabled; /* These are used to know the size of the window for the connection that * belongs to this player. The unit here is characters. */ int win_x_s; int win_x_e; int win_y_s; int win_y_e; /* How big is his screen? How many dots fit it? */ int imgwi; int imghe; /* How much of the world does he see? How many dots should we fit into his screen? */ int world_wi; int world_he; }; @ @ @ typedef struct MatFont MatFont; struct MatFont { int width, height; char *data; }; @ This is used to identify the ship in the connection. |conn_id| is the id for this ship among the ships for this connection. |conn| points to the connection or, if it was lost, its set to |NULL| (this can happen, for example, if the connection is gone but it is impossible to destroy the ship because there are references to it in other objects). |conn_hash_next| and |conn_hash_prev| point to the previous and next nodes in the list in the hash of ships for the connection, while |conn_list_next| and |conn_list_prev| are used to traverse the list with all the ships for the connection. @= MatConnection *conn; int conn_id; MatMovingObj *conn_hash_next; MatMovingObj *conn_hash_prev; MatMovingObj *conn_list_next; MatMovingObj *conn_list_prev; @ We need to keep track of the current view for the player controling this ship. Basically, he may see the objects surrounding any of the ships. |view| is the object the player is currently viewing. Note that, for the moment, |view| must point to an object of type |MAT_MOVING_OBJ_SHIP|. @= MatMovingObj *view; @ We need a way to keep track of what other players are seeing the world as it looks like around any given ship. This is important cause when the player disconnects, we need a fast way to know what other players where looking to the world through him. |viewers| points to a list with all the ships viewing the world as the current. The list is traversed following the |view_next| and |view_prev| fields. @= MatMovingObj *viewers; MatMovingObj *view_next; MatMovingObj *view_prev; @ @= #define MAT_MOVING_OBJ_SHIP 0 #define MAT_MOVING_OBJ_BULLET 1 #define MAT_MOVING_OBJ_AST 2 #define MAT_MOVING_OBJ_SMART 3 #define MAT_MOVING_OBJ_MOVE_NORMAL 1 #define MAT_MOVING_OBJ_MOVE_DEAD 2 struct MatMovingObj { @ MatUniverse *un; /* If draw is 0, we don't draw this object. */ int draw; /* If crash is 0, this object won't crash against others. */ int crash; /* pos_x and pos_y specify the position of the object, relative to the place * where its image begins (upper left corner), not the center of the object. */ double pos_x; double pos_y; MatImage *img; /* sp_x and sp_y hold the speed in the x and y coordinate. sp holds the * composite speed (that is, sp * sp = sp_x * sp_x + sp_y * sp_y). */ double sp_x; double sp_y; double sp; double tmp_sp_x; double tmp_sp_y; /* ang is the current angle of this object, such that 0 <= ang < arg_ang. * sp_ang is the speed of rotation. */ double ang; double sp_ang; unsigned char *pal; MatMovingObj *next; MatMovingObj *prev; MatMovingObj *nexttype; MatMovingObj *prevtype; /* rm_next is used to maintain a single linked list of objects that should be * removed. The last node of the object has rm_next == &main. This is so we * can make assertions on all objects that should not be removed having * rm_next == NULL. That is, to know if an object should be removed, * evaluate rm_next != NULL. * * Also, it is worth noticing that ships are not kept in this list. Other * objects are kept in the |objs_rm| list for their universe (see the * definition of |MatUniverse|). */ MatMovingObj *rm_next; int type; union { MatShip player; MatBullet bullet; MatAst ast; MatSmartObj smart; } info; }; @ There are times when it is impossible to free an object because there are references to it in other structs. Consider, for example, that a player might shot a missile and disconnect. The missile has a reference to the ship so removing the ship before the missile will probably cause a crash (when the missile hits another player, the reference is followed to find out the name of the player who shot it). To solve that problem, we use reference counting on the moving objects, only freeing one when it is no longer referenced. References to the objects in the universe they are in are not counted, since there is no way for an object to exist outside of a universe. On the other hand, references to a ship from a connection should be counted. This is because a ship may exist after its connection has been gone. Don't forget to set this field to 0 everytime you create a new object. Actually, since at creation time a ship will always be referenced from a connection, you'll likely set it to 1 directly for ships. @= int refs; @ Now we need code to increase and decrease the number of references to a ship. @d MAT_MOVING_OBJ_REF(sh) sh->refs ++; @= void mat_moving_obj_unref ( MatMovingObj *ship ); @ @= void mat_moving_obj_unref ( MatMovingObj *ship ) { ASSERT(ship->refs > 0); ship->refs --; if (ship->refs == 0) { MAT_SHIP_VIEW_CHECK(ship->un); MAT_SHIP_VIEW_RM(ship); @; ship->un->players_real --; VERBOSE("Killing player: %s\n", ship->info.player.name); if (ship->prevtype) ship->prevtype->nexttype = ship->nexttype; else ship->un->players_head = ship->nexttype; if (ship->nexttype) ship->nexttype->prevtype = ship->prevtype; else ship->un->players_tail = ship->prevtype; if (ship->prev) ship->prev->next = ship->next; else ship->un->objs = ship->next; if (ship->next) ship->next->prev = ship->prev; MAT_SHIP_VIEW_CHECK(ship->un); free(ship); } } @ @= { if (sh->info.player.view_prev) sh->info.player.view_prev->info.player.view_next = sh->info.player.view_next; else } @ @= { MatMovingObj *i = ship->info.player.viewers; while (i) { MatMovingObj *tmp = i->info.player.view_next; ASSERT(i != ship); sprintf(message_get(i), "-=> Zip. %s disappears.", ship->info.player.name); i->info.player.view = i; if (i->info.player.viewers) i->info.player.viewers->info.player.view_prev = i; i->info.player.view_prev = NULL; i->info.player.view_next = i->info.player.viewers; i->info.player.viewers = i; i = tmp; } } @* Global variables @d MAT_UNIVERSES_HASH_SIZE 1 @= typedef void (*MatCrashHandler) (MatMovingObj *, MatMovingObj *); MatCrashHandler crash_handler[] = { player_crash_handler, bullet_crash_handler, ast_crash_handler }; @ @ MatUniverse *mat_universes[MAT_UNIVERSES_HASH_SIZE]; int mat_universes_count; MatConnection *connections = NULL; MatLocation mat_location_default = { {0, 0, 0}, 0, {1, 1, 1} }; MatFont font; /* Socket for incoming players. */ MatSocketT mat_mainsock; /* Socket for incoming machines. */ MatSocketT mat_mainsock_machine; int players_count = 0; @ struct aa_font *graph_font = &aa_font16; unsigned short *graph_table; unsigned short *graph_filltable; struct parameters *graph_parameters; @ @d MAT_UNIVERSES_FIND(xr, xid) for (xr = mat_universes[xid % MAT_UNIVERSES_HASH_SIZE]; xr && xr->id != xid; xr = xr->next_hash); @d MAT_UNIVERSES_ADD(un) { int i; un->id = mat_universes_count ++; i = un->id % MAT_UNIVERSES_HASH_SIZE; un->next_hash = mat_universes[i]; mat_universes[i] = un; } @= { int i; for (i = 0; i < MAT_UNIVERSES_HASH_SIZE; i ++) mat_universes[i] = NULL; } @ If arg_chat evaluates to false, the players won't be able to chat. If you change |MAT_PASSWORD_MAX|, change |MAT_PASSWORD_BLANK|. It should hold |MAT_PASSWORD_MAX| spaces. @d MAT_PASSWORD_MAX 8 @d MAT_PASSWORD_BLANK " " @d MAT_BACKGROUND_DOTS 1 @d MAT_BACKGROUND_IMG 2 @d MAT_IMGWIDTH_DEFAULT 80 * 4 @d MAT_IMGHEIGHT_DEFAULT 24 * 4 @= char *program_name; int arg_compress = 1; unsigned long arg_usleep = 100000; int arg_bg_dots = 1; int arg_bg_size = 0; int arg_bg_adj = 0; int arg_bg_color_max = -1; int arg_max_players = 0; int arg_bold = 0; char *arg_ship_graphic_path = NULL; double arg_ship_friction = 0; int arg_imgwidth = MAT_IMGWIDTH_DEFAULT; int arg_health = 1000; int arg_port = 7993; int arg_port_machine = 7793; int arg_mapsize_x = 2000; int arg_mapsize_y = 1600; int arg_limits = 0; int arg_lives = 5; int arg_ang = 64; int arg_chat = 1; int arg_ppc = 1; int arg_teams_count = 0; int arg_teams_safe = 0; int arg_teams_share = 1; MatTeam *arg_teams_head = NULL; MatTeam *arg_teams_tail = NULL; int arg_radar = 1; int arg_visible_init = 0; double arg_ang_speed_max = 8.0 / STEPS_MOVEMENT; int arg_fly_back = 0; int arg_brake = 1; int arg_space = 1; double arg_speed_max = 9.0 / STEPS_MOVEMENT; char *arg_password = NULL; int arg_ast_num = 4; @ By default, when asked to terminate, we won't free anything (to avoid possibly causing page faults). However, when running Matanza under a memory leaks detector, freeing everything makes things easier. We will use parameter |arg_free_at_exit| to know whether we should free memory when terminating the program. @= int arg_free_at_exit = 0; @ Matanza can perform motion blur on objects that are moving. The amount of blur is proportional to their speeds. |arg_motion_blur| is used to control whether Matanza should apply motion blur to objects or just print them as they are. @= int arg_motion_blur = 1; @* Functions @= @ @ @ @ @= @ void mat_input (MatConnection *p); @* The main program @= int main (int argc, char **argv) { @; while (1) if (players_count == 0) { @; @; } else { unsigned long old, now; GETMICROSECOND_GENERIC(old); @; @; @; @; GETMICROSECOND_GENERIC(now); @; } } @ @= { VERBOSE("-=> accept incomming connections\n"); mat_accept(mat_mainsock, 0); mat_accept(mat_mainsock_machine, 1); VERBOSE("<=- accept incomming connections\n"); } @ @= { int i; MatUniverse *un; VERBOSE("-=> update universes\n"); for (i = 0; i < MAT_UNIVERSES_HASH_SIZE; i ++) for (un = mat_universes[i]; un; un = un->next_hash) @; VERBOSE("<=- update universes\n"); } @ @= { fd_set i; ASSERT(players_count == 0); FD_ZERO(&i); FD_SET(mat_mainsock, &i); FD_SET(mat_mainsock_machine, &i); VERBOSE("-=> select\n"); select(MAX(mat_mainsock, mat_mainsock_machine) + 1, &i, NULL, NULL, NULL); VERBOSE("<=- select\n"); } @ @= { MatImage *img; img = un->mask; if (!img) crash_wall = 0; else { crash_x = ((int) obj->pos_x + obj->img->w / 2) % un->mapsize_x; crash_y = ((int) obj->pos_y + obj->img->h / 2) % un->mapsize_y; if (crash_x >= img->w || crash_y >= img->h) crash_wall = 0; else { ASSERT(img->img); ASSERT(un->location[img->img[crash_x + crash_y * img->w]]); crash_wall = un->location[img->img[crash_x + crash_y * img->w]]->crash[obj->type]; } } } @ @= { switch (obj->type) { case MAT_MOVING_OBJ_BULLET: /* Remove the bullet and go on. */ obj->info.bullet.expires = 0; break; case MAT_MOVING_OBJ_SHIP: if (arg_space) @; break; case MAT_MOVING_OBJ_AST: if (arg_space) { obj->sp_x = -obj->sp_x; obj->sp_y = -obj->sp_y; } break; } } @ @= { int pos0, pos1, pos2; double spx, spy; @; /* * +-+-+ * |0|1| * +-+-+ * |3|2| * +-+-+ * * 3 is where the crash took place. */ } @ @= { int x0, y0, x1, y1, x2, y2; spx = obj->sp_x; spy = obj->sp_y; if (spx > 0) { if (spy > 0) { x0 = crash_x - 1; y0 = crash_y; x1 = crash_x - 1; y1 = crash_y - 1; x2 = crash_x; y2 = crash_y - 1; } else { x0 = crash_x; y0 = crash_y + 1; x1 = crash_x - 1; y1 = crash_y + 1; x2 = crash_x - 1; y2 = crash_y; } } else { if (spy > 0) { x0 = crash_x; y0 = crash_y - 1; x1 = crash_x + 1; y1 = crash_y - 1; x2 = crash_x + 1; y2 = crash_y; } else { x0 = crash_x + 1; y0 = crash_y; x1 = crash_x + 1; y1 = crash_y + 1; x2 = crash_x; y2 = crash_y + 1; } } } @ We don't bother to update the world if we have no players or if the game is paused. @d STEPS_MOVEMENT 10 @= { if (!un->pause && un->players_real) { un->updates++; @; @; @; @; @; } } @ @= { MatMovingObj *obj; for (i = 0; i < STEPS_MOVEMENT; i ++) for (obj = un->objs; obj; obj = obj->next) if (!obj->rm_next) { if (obj->crash) { int crash_wall, crash_x, crash_y; @; if (crash_wall) @@; else @; } @; @; } } @ @= { MatMovingObj *b; ASSERT(un); for (b = un->bullets; b; b = b->nexttype) { ASSERT(b->info.bullet.expires >= 0); if (b->info.bullet.expires -- == 0) { REMOVE_QUEUE_ADD(b); ASSERT(b->info.bullet.src); ASSERT(b->info.bullet.src->refs > 0); mat_moving_obj_unref(b->info.bullet.src); } } } @ @= { MatMovingObj *pl; for (pl = un->players_head; pl; pl = pl->nexttype) { if (pl->info.player.bullets_expire > 0) pl->info.player.bullets_expire--; if (pl->info.player.ship_speed_inc > 0) pl->info.player.ship_speed_inc--; if (pl->alpha_mod) pl->alpha_mod(pl); if (!pl->info.player.visible && pl->info.player.visible_exp -- <= 0) { pl->info.player.visible = 1; VISIBILITY_BROADCAST(pl); } } } @ @= { MatImage *img; img = un->mask; if (img) { int x, y; x = (int) obj->pos_x + obj->img->w / 2 % obj->un->mapsize_x; y = (int) obj->pos_y + obj->img->h / 2 % obj->un->mapsize_y; if (x < img->w && y < img->h) { double index; index = un->location[img->img[x + y * img->w]]->move[obj->type]; if (index != 1.0) { (obj)->sp_x *= (index); (obj)->sp_y *= (index); (obj)->sp = sqrt(obj->sp_x * obj->sp_x + obj->sp_y * obj->sp_y); } } } } @ @d REMOVE_QUEUE_ADD(obj) { obj->rm_next = obj->un->objs_rm; obj->un->objs_rm = obj; } @= { MatMovingObj *tmp; while (un->objs_rm != (void *) &main) { MatMovingObj *next; next = un->objs_rm->rm_next; ASSERT(next); if (un->objs_rm->nexttype) un->objs_rm->nexttype->prevtype = un->objs_rm->prevtype; if (un->objs_rm->prevtype) un->objs_rm->prevtype->nexttype = un->objs_rm->nexttype; else switch (un->objs_rm->type) { case MAT_MOVING_OBJ_SHIP: break; case MAT_MOVING_OBJ_BULLET: un->bullets = un->bullets->nexttype; break; case MAT_MOVING_OBJ_AST: un->ast = un->ast->nexttype; break; default: ASSERT(0); } DEL_MOVING_OBJ(un->objs_rm); free(un->objs_rm); un->objs_rm = next; } ASSERT_FOR(tmp = un->players_head; tmp; tmp = tmp->nexttype) ASSERT(!tmp->rm_next); ASSERT_FOR(tmp = un->bullets; tmp; tmp = tmp->nexttype) ASSERT(!tmp->rm_next); ASSERT_FOR(tmp = un->ast; tmp; tmp = tmp->nexttype) ASSERT(!tmp->rm_next); } @ @= { MatMovingObj *i; ASSERT((int) obj->pos_x >= 0); ASSERT((int) obj->pos_x < un->mapsize_x); ASSERT((int) obj->pos_y >= 0); ASSERT((int) obj->pos_y < un->mapsize_y); for (i = obj->next; i; i = i->next) if (!i->rm_next && i->crash) { int crash = 0; if (obj->img && i->img && @) { MatMovingObj *src, *dst; int xmod, ymod, xbeg, xend, ybeg, yend, xtmp, ytmp; ASSERT((int)i->pos_x >= 0); ASSERT((int)i->pos_x < un->mapsize_x); ASSERT((int)i->pos_y >= 0); ASSERT((int)i->pos_y < un->mapsize_y); if (obj->img->h * obj->img->w <= i->img->h * i->img->w) src = obj, dst = i; else src = i, dst = obj; xmod = dst->pos_x - src->pos_x; if (xmod > 0 && xmod > un->mapsize_x / 2) xmod = un->mapsize_x - xmod; else if (xmod < 0 && xmod < -un->mapsize_x / 2) xmod = -un->mapsize_x - xmod; ASSERT(ABS(xmod) < src->img->w || ABS(xmod) < dst->img->w); ymod = dst->pos_y - src->pos_y; if (ymod > 0 && ymod > un->mapsize_y / 2) ymod = un->mapsize_y - ymod; else if (ymod < 0 && ymod < -un->mapsize_y / 2) ymod = -un->mapsize_y - ymod; ASSERT(ABS(ymod) < src->img->h || ABS(ymod) < dst->img->h); xbeg = MAX(0, xmod); xend = MIN(src->img->w, xmod + dst->img->w); ybeg = MAX(0, ymod); yend = MIN(src->img->h, ymod + dst->img->h); for (ytmp = ybeg; ytmp < yend; ytmp ++) for (xtmp = xbeg; xtmp < xend; xtmp ++) { ASSERT(xtmp < src->img->w); ASSERT(ytmp < src->img->h); ASSERT(xtmp - xmod < dst->img->w); ASSERT(ytmp - ymod < dst->img->h); if ( src->pal[src->img->img[(xtmp ) + (ytmp ) * src->img->w]] > 0 && dst->pal[dst->img->img[(xtmp - xmod) + (ytmp - ymod) * dst->img->w]] > 0) { crash = 1; xtmp = xend; ytmp = yend; } } } else if (obj->img || i->img) { MatMovingObj *src, *b; src = obj->img ? obj : i ; b = obj->img ? i : obj; @; } if (crash) { ASSERT( i->crash); ASSERT(obj->crash); crash_handler[i->type](i, obj); } } } @ I optimized this as much as I could. It should be very fast. :) |CHECK_HIT_BULLET| takes as arguments a variable where it is to leave the results (cache), the bullet's position (bpos), the object's position (opos), the object's size (osize) and the map's size (msize) and checks to see if the bullet is close to the object. If it isn't, cache is left with a value of -1. If it is, cache is left with the coordinate the bullet is on inside the object's image. @d CHECK_HIT_BULLET(cache, bpos, opos, osize, msize) { cache = bpos - opos; if (0 <= cache && cache < osize) cache = cache ; else if ( msize + cache < osize) cache = cache + msize; else cache = -1; ASSERT(cache == -1 || (cache >= 0 && cache < osize)); } @= { int posx; CHECK_HIT_BULLET(posx, b->pos_x, src->pos_x, src->img->w, un->mapsize_x); if (posx != -1) { int posy; CHECK_HIT_BULLET(posy, b->pos_y, src->pos_y, src->img->h, un->mapsize_y); if (posy != -1) { ASSERT(!crash); crash = src->pal[src->img->img[posx + posy * src->img->w]] > 0; } } } @ @= void ast_crash_handler ( MatMovingObj *, MatMovingObj * ); void bullet_crash_handler ( MatMovingObj *, MatMovingObj * ); void player_crash_handler ( MatMovingObj *, MatMovingObj * ); @ @= void ast_crash_handler ( MatMovingObj *ast, MatMovingObj *obj ) { ASSERT(obj); switch (obj->type) { case MAT_MOVING_OBJ_AST: break; case MAT_MOVING_OBJ_BULLET: crash_handler[obj->type](obj, ast); break; case MAT_MOVING_OBJ_SHIP: crash_handler[obj->type](obj, ast); break; case MAT_MOVING_OBJ_SMART: break; default: ASSERT(0); } } @ @= void bullet_crash_handler ( MatMovingObj *b, MatMovingObj *obj ) { ASSERT(obj); switch (obj->type) { case MAT_MOVING_OBJ_BULLET: break; case MAT_MOVING_OBJ_AST: @; break; case MAT_MOVING_OBJ_SHIP: @; break; case MAT_MOVING_OBJ_SMART: break; default: ASSERT(0); } } @ @= void player_crash_handler ( MatMovingObj *p, MatMovingObj *obj ) { ASSERT(obj); ASSERT(p->type == MAT_MOVING_OBJ_SHIP); switch (obj->type) { case MAT_MOVING_OBJ_AST: @; break; case MAT_MOVING_OBJ_SHIP: @; break; case MAT_MOVING_OBJ_BULLET: crash_handler[obj->type](obj, p); break; case MAT_MOVING_OBJ_SMART: break; default: ASSERT(0); } } @ @d CRASH_SHIP_DAMAGE 400 @d MESSAGE_CRASH_SHIP(x, y) { if (x->info.player.health > 0) { if (dmg > 0) sprintf(message_get(x), "-=> You crashed against player %s ! [Health:%d%%]", y->info.player.name, HEALTH(x)); } else { int sent_out; MatMovingObj *i; PLAYER_DEAD_REGISTER(sent_out, x); for (i = x->un->players_head; i; i = i->nexttype) if (arg_teams_count > 0) { sprintf(message_get(i), "-=> BOOM ! %s of %s died in crash against %s of %s.", x->info.player.name, x->info.player.team->name, y->info.player.name, y->info.player.team->name); if (sent_out) sprintf(message_get(i), "-=> %s of %s is sent out of the game.", x->info.player.name, x->info.player.team->name); } else { sprintf(message_get(i), "-=> BOOM ! %s died in crash against %s.", x->info.player.name, y->info.player.name); if (sent_out) sprintf(message_get(i), "-=> %s is sent out of the game.", x->info.player.name); } if (!sent_out) { MatMovingObj *o; if (arg_teams_count && arg_teams_share) for (o = x->info.player.team->head; o; o = o->info.player.team_next) sprintf(message_get(o), "-=> [%s] Arg, we have lost %d ships now !", x->info.player.team->name, x->info.player.team->times_dead); else sprintf(message_get(x), "-=> You have lost %d ships now !", x->info.player.times_dead); start_game(x); } else GAME_OVER_MODE(x); } } @= { int dmg; ASSERT(p->un == obj->un); if (!arg_space) return; dmg = p->un->crash_damage[MAT_MOVING_OBJ_SHIP]; obj->info.player.health -= dmg; p->info.player.health -= dmg; if (arg_space) { p->sp_x = - p->sp_x; p->sp_y = - p->sp_y; obj->sp_x = -obj->sp_x; obj->sp_y = -obj->sp_y; } MESSAGE_CRASH_SHIP( p, obj); MESSAGE_CRASH_SHIP(obj, p); } @ @= { ASSERT(obj); ASSERT(obj->type == MAT_MOVING_OBJ_AST); ASSERT(p); ASSERT(p->type == MAT_MOVING_OBJ_SHIP); if (!arg_space) return; /* Make damage. */ p->info.player.health -= 200; if (arg_space) { p->sp_x = -p->sp_x; p->sp_y = -p->sp_y; obj->sp_x = -obj->sp_x; obj->sp_y = -obj->sp_y; } if (p->info.player.health <= 0) @@; else sprintf(message_get(p), "-=> You crashed against an asteroid ! [Health:%d%%]", HEALTH(p)); } @ @= { ASSERT(b->info.bullet.expires >= 0); if (!b->info.bullet.expires) return; /* Remove the bullet. */ b->info.bullet.expires = 0; /* Make damage. */ obj->info.ast.health -= mat_bullets_damage[b->info.bullet.type]; if (obj->info.ast.health <= 0) @@; else sprintf(message_get(b->info.bullet.src), mat_bullets_hit_ast[b->info.bullet.type]); } @ @= { VERBOSE("Boom, asteroid broke\n"); ASSERT(obj); ASSERT(obj->type == MAT_MOVING_OBJ_AST); ASSERT(b); ASSERT(b->type == MAT_MOVING_OBJ_BULLET); ASSERT(b->info.bullet.src); if (b->info.bullet.src->type == MAT_MOVING_OBJ_SHIP) sprintf(message_get(b->info.bullet.src), "-=> BOOM, you broke an asteroid to pieces !"); REMOVE_QUEUE_ADD(obj); if (obj->info.ast.size < 1) @; } @ When a player has crashed a big asteroid, it breaks down into parts. The asteroid is removed and four new asteroids are created. @d RND_SP() (((double) (rand() % 20)) / 100.0 + 0.1) @= { int ns; ns = obj->info.ast.size + 1; AST_ADD_POS(ns, obj->pos_x, obj->pos_y, obj->sp_x + RND_SP(), obj->sp_y + RND_SP(), obj->un); AST_ADD_POS(ns, obj->pos_x, obj->pos_y, obj->sp_x + RND_SP(), obj->sp_y - RND_SP(), obj->un); AST_ADD_POS(ns, obj->pos_x, obj->pos_y, obj->sp_x - RND_SP(), obj->sp_y + RND_SP(), obj->un); AST_ADD_POS(ns, obj->pos_x, obj->pos_y, obj->sp_x - RND_SP(), obj->sp_y - RND_SP(), obj->un); } @ @= { if (!b->info.bullet.expires || b->info.bullet.src == obj) return; /* Remove the bullet. */ b->info.bullet.expires = 0; /* Make damage. */ obj->info.player.health -= mat_bullets_damage[b->info.bullet.type]; if (obj->info.player.health <= 0) @@; else switch(b->info.bullet.src->type) { case MAT_MOVING_OBJ_SHIP: sprintf(message_get(obj), "-=> Argh! %s got you! [Health:%d%%]", b->info.bullet.src->info.player.name, HEALTH(obj)); sprintf(message_get(b->info.bullet.src), mat_bullets_hit[b->info.bullet.type], obj->info.player.name); break; case MAT_MOVING_OBJ_SMART: sprintf(message_get(obj), "-=> Argh! An alien got you! [Health:%d%%]", HEALTH(obj)); break; default: ASSERT(0); } } @ @= ( ( ((int)(obj->pos_x - i->pos_x) >= 0 && (int)(obj->pos_x - i->pos_x) < i->img->w) || ((int)( i->pos_x - obj->pos_x) >= 0 && (int)( i->pos_x - obj->pos_x) < obj->img->w) || (un->mapsize_x + (int)(obj->pos_x - i->pos_x) < i->img->w) || (un->mapsize_x + (int)( i->pos_x - obj->pos_x) < obj->img->w) ) && ( ((int)(obj->pos_y - i->pos_y) >= 0 && (int)(obj->pos_y - i->pos_y) < i->img->h) || ((int)( i->pos_y - obj->pos_y) >= 0 && (int)( i->pos_y - obj->pos_y) < obj->img->h) || (un->mapsize_y + (int)(obj->pos_y - i->pos_y) < i->img->h) || (un->mapsize_y + (int)( i->pos_y - obj->pos_y) < obj->img->h) ) ) @ @= { ASSERT(- un->mapsize_x < (int) obj->sp_x); ASSERT((int) obj->sp_x < un->mapsize_x); ASSERT((int) obj->pos_x >= 0); ASSERT((int) obj->pos_x < un->mapsize_x); ASSERT(- un->mapsize_y < (int) obj->sp_y); ASSERT((int) obj->sp_y < un->mapsize_y); ASSERT((int) obj->pos_y >= 0); ASSERT((int) obj->pos_y < un->mapsize_y); obj->pos_x += obj->sp_x; obj->pos_y += obj->sp_y; ASSERT(- un->mapsize_x <= (int) obj->pos_x); ASSERT((int) obj->pos_x < 2 * un->mapsize_x); ASSERT(- un->mapsize_y <= (int) obj->pos_y); ASSERT((int) obj->pos_y < 2 * un->mapsize_y); if ((int) obj->pos_x < 0) { if (!arg_limits || obj->type != MAT_MOVING_OBJ_SHIP) { obj->pos_x += un->mapsize_x; ASSERT(0 <= (int) obj->pos_x); } else { obj->pos_x = 0; obj->sp_x = 0; } } else if ((int) obj->pos_x >= un->mapsize_x) { if (!arg_limits || obj->type != MAT_MOVING_OBJ_SHIP) { obj->pos_x -= un->mapsize_x; ASSERT((int) obj->pos_x < un->mapsize_x); } else { obj->pos_x = un->mapsize_x - 1; obj->sp_x = 0; } } if ((int) obj->pos_y < 0) { if (!arg_limits || obj->type != MAT_MOVING_OBJ_SHIP) { obj->pos_y += un->mapsize_y; ASSERT(0 <= (int) obj->pos_y); } else { obj->pos_y = 0; obj->sp_y = 0; } } else if ((int) obj->pos_y >= un->mapsize_y) { if (!arg_limits || obj->type != MAT_MOVING_OBJ_SHIP) { obj->pos_y -= un->mapsize_y; ASSERT((int) obj->pos_y < un->mapsize_y); } else { obj->pos_y = un->mapsize_y; obj->sp_y = 0; } } ASSERT((int) obj->pos_x >= 0); ASSERT((int) obj->pos_x < un->mapsize_x); ASSERT((int) obj->pos_y >= 0); ASSERT((int) obj->pos_y < un->mapsize_y); ASSERT((int) obj->ang >= 0); ASSERT((int) obj->ang < arg_ang); obj->ang += obj->sp_ang; if ((int) obj->ang >= arg_ang) obj->ang -= arg_ang; else if ((int) obj->ang < 0) obj->ang += arg_ang; if (!arg_space && obj->sp_ang != 0 && obj->type == MAT_MOVING_OBJ_SHIP) { obj->sp_x = obj->sp * mat_sin[(int) obj->ang]; obj->sp_y = obj->sp * mat_cos[(int) obj->ang]; } ASSERT((int) obj->ang >= 0); ASSERT((int) obj->ang < arg_ang); } @ @d PLAYER_DEAD_REGISTER(sent_out, pl) { pl->info.player.times_dead ++; sent_out = pl->info.player.times_dead >= arg_lives; if (arg_teams_count) { pl->info.player.team->times_dead ++; if (arg_teams_share && pl->info.player.team->times_dead >= arg_lives) sent_out = 1; } } @ @d GAME_OVER_MODE(x) { ASSERT((x)->type == MAT_MOVING_OBJ_SHIP); ASSERT((x)->alpha_mod == NULL); (x)->draw = 0; (x)->crash = 0; (x)->alpha = 0; (x)->info.player.game_over = 1; (x)->sp = 0; (x)->sp_x = (x)->sp_y = 0; } @ @= { int sent_out; MatMovingObj *i; VERBOSE("xxxx player killed by asteroid\n"); ASSERT(p); ASSERT(p->type == MAT_MOVING_OBJ_SHIP); ASSERT(obj); ASSERT(obj->type == MAT_MOVING_OBJ_AST); ASSERT(p->un == obj->un); PLAYER_DEAD_REGISTER(sent_out, p); for (i = p->un->players_head; i; i = i->nexttype) if (arg_teams_count > 0) { sprintf(message_get(i), "-=> KABOOM ! %s of %s is destroyed by an asteroid . . .", p->info.player.name, p->info.player.team->name); if (sent_out) sprintf(message_get(i), "-=> %s of %s is sent out of the game.", p->info.player.name, p->info.player.team->name); } else { sprintf(message_get(i), "-=> KABOOM ! %s is destroyed by an asteroid . . .", p->info.player.name); if (sent_out) sprintf(message_get(i), "-=> %s is sent out of the game.", p->info.player.name); } if (!sent_out) { if (arg_teams_count && arg_teams_share) for (i = p->info.player.team->head; i; i = i->info.player.team_next) sprintf(message_get(i), "-=> [%s] Arg, we have lost %d ships now !", p->info.player.team->name, p->info.player.team->times_dead); else sprintf(message_get(p), "-=> You have lost %d ships now !", p->info.player.times_dead); start_game(p); } else GAME_OVER_MODE(p); } @ TODO: Don't make his ship disappear immediately! One explotion would be very nice. Or at least have him fade into nothingness. @= { int sent_out; MatMovingObj *i; ASSERT(obj); ASSERT(obj->type == MAT_MOVING_OBJ_SHIP); ASSERT(b); ASSERT(b->type == MAT_MOVING_OBJ_BULLET); ASSERT(b->info.bullet.src); ASSERT(b->info.bullet.src->type == MAT_MOVING_OBJ_SHIP); ASSERT(obj != b->info.bullet.src); ASSERT(obj->un == b->un); PLAYER_DEAD_REGISTER(sent_out, obj); for (i = obj->un->players_head; i; i = i->nexttype) if (arg_teams_count > 0) { sprintf(message_get(i), "-=> KABOOM ! %s of %s is destroyed by %s of %s . . .", obj->info.player.name, obj->info.player.team->name, b->info.bullet.src->info.player.name, b->info.bullet.src->info.player.team->name); if (sent_out) sprintf(message_get(i), "-=> %s of %s is sent out of the game.", obj->info.player.name, obj->info.player.team->name); } else { sprintf(message_get(i), "-=> KABOOM ! %s is destroyed by %s . . .", obj->info.player.name, b->info.bullet.src->info.player.name); if (sent_out) sprintf(message_get(i), "-=> %s is sent out of the game.", obj->info.player.name); } if (!sent_out) { if (arg_teams_count && arg_teams_share) for (i = obj->info.player.team->head; i; i = i->info.player.team_next) sprintf(message_get(i), "-=> [%s] Arg, we have lost %d ships now !", obj->info.player.team->name, obj->info.player.team->times_dead); else sprintf(message_get(obj), "-=> You have lost %d ships now !", obj->info.player.times_dead); start_game(obj); } else { GAME_OVER_MODE(obj); /* YYYY */ //un->players_real --; //obj->info.player.conn->state = MAT_STATE_DEAD; //main_menu_begin(obj->info.player.conn); } } @ @= { MatConnection *i; for (i = connections; i; i = i->next) if (i->state != MAT_STATE_REMOVE && i->anim_func) i->anim_func(i); } @ @= { unsigned long usec; unsigned long elapsed; elapsed = now - old; usec = elapsed < arg_usleep ? arg_usleep - elapsed : 0; ASSERT(usec <= arg_usleep); if (usec > 0) USLEEP_GENERIC(usec); } @ @= { ASSERT(con); ASSERT(con->state == MAT_STATE_REMOVE); if (con->prev) con->prev->next = con->next; else connections = con->next; if (con->next) con->next->prev = con->prev; players_count --; free (con); } @ @= { MatConnection *con; con = connections; while (con) if (con->state == MAT_STATE_REMOVE) { MatConnection *tmp; tmp = con->next; @; con = tmp; } else { mat_input(con); con = con->next; } } @ @= void mat_input (MatConnection *con) { @; @; @; } @ Here we make sure there are at least 128 bytes of space in the player's buffer. Otherwise, we increase its size. @= if (con->bufsiz - con->buflen < 128) { con->bufsiz = con->bufsiz ? con->bufsiz * 2 : 128; con->buffer = realloc(con->buffer, con->bufsiz + 1); } @ @= void mat_accept ( MatSocketT fildes, int machine ); @ Here we loop accepting connections. When no more connections are ready, we return. |machine| is evaluated to know if this socket receives connections from players or from machines. TODO: Make some checks against DoS attacks: we shouldn't allow more than X connections from the same host. @= void mat_accept ( MatSocketT source, int machine ) { MatSocketT result; socklen_t in_con_size = sizeof(struct sockaddr_in); struct sockaddr_in in_con; while (1) { do { VERBOSE("-=> accept [fd:%d]\n", source); result = accept(source, (struct sockaddr*)&in_con, &in_con_size); VERBOSE("<=- accept [fd:%d] [result:%d]\n", source, result); } while (result == SOCKET_ERROR && result == SOCKET_CALL_INTR); if (result == SOCKET_ERROR) @@; else @; } } @ @= { VERBOSE("error in accept: %d\n", SOCKET_ERRNO()); switch (SOCKET_ERRNO()) { #ifdef EAGAIN case EAGAIN: #endif #ifdef EWOULDBLOCK # if EWOULDBLOCK != EAGAIN case EWOULDBLOCK: # endif #endif #ifdef WSAEWOULDBLOCK # if WSAEWOULDBLOCK != EAGAIN case WSAEWOULDBLOCK: # endif #endif return; default: fprintf(stderr, "%s: code: %d\n", program_name, SOCKET_ERRNO()); fprintf(stderr, "%s: accept: %s\n", program_name, strerror(SOCKET_ERRNO())); exit(EXIT_FAILURE); } } @ This code gets executed right after a new connection has been accepted (calling |accept|). The new file descriptor is available at |result|. |machine| can be evaluated to know whether the peer is a player (telnet client) or a machine (speaking MMP). @= { MatConnection *con; int on = 1; con = malloc(sizeof(MatConnection)); if (!con) { /* TODO: Kill this connection rather than the whole program. */ fprintf(stderr, "%s: %s\n", program_name, strerror(errno)); exit(EXIT_FAILURE); } con->fd = result; @; #if HAVE_SETSOCKOPT # ifdef SO_KEEPALIVE # ifdef SOL_SOCKET VERBOSE("setsockopt [fd:%d][option:SO_KEEPALIVE]\n", con->fd); if (setsockopt(con->fd, SOL_SOCKET, SO_KEEPALIVE, (void *) &on, sizeof(on)) == -1) fprintf(stderr, "%s: Warning: setsockopt: SO_KEEPALIVE: %s\n", program_name, strerror(errno)); # endif # endif #endif /* Make socket nonblocking */ NONBLOCKING_GENERIC(result); con->out_buf = NULL; con->out_len = 0; con->out_siz = 0; ASSERT(source == mat_mainsock || source == mat_mainsock_machine); if (arg_max_players == 0 || players_count < arg_max_players) { if (source == mat_mainsock) @@; else @@; } else @; } @ This code gets executed when a connection arrives but the server is crowded. We simply send a message, close the socket and free some memory. Note that the actual message we send depends on whether the connection is that of a player or a machine. TODO: If the connection is that of a player, send a nicer message. @= { ASSERT(con); if (source == mat_mainsock) mat_printf(con, "%s", "Sorry, the server is full. Please try again later.\n"); else mat_printf(con, "%c", MMP_SERVER_INITIAL_FULL); mat_out_flush(con); free(con->out_buf); free(con); } @ Here we don't reverse lookup the address to the name because it may take long amounts of time: The whole game would freeze during resolution. If |inet_ntop| is available, we use it. On those systems, |inet_ntoa| is deprecated. It supports IPV6. On older machines where it's not available, we try with |inet_ntoa|. To be safe, we make sure |inet_ntoa| is actually available and, if it isn't, we report a bogus address. All this macros should leave |real_buffer| pointing to the address. For the time being, we free |real_buffer|. In the future, we will add it to the players' structures. @= { #if HAVE_INET_NTOP @; #elif HAVE_INET_NTOA @; #else @; #endif ASSERT(con->addr); VERBOSE("Connection from: %s\n", con->addr); } @ If we don't know how to get the IP address, we use a default string. @= { con->addr = strdup("Unknown"); if (!con->addr) { fprintf(stderr, "%s: %s\n", program_name, strerror(errno)); exit(EXIT_FAILURE); } } @ @= { char *tmp; tmp = inet_ntoa(in_con.sin_addr); ASSERT(tmp); con->addr = strdup(tmp); if (!con->addr) { fprintf(stderr, "%s: %s\n", program_name, strerror(errno)); exit(EXIT_FAILURE); } } @ @= { char buffer[256]; if (!inet_ntop(in_con.sin_family, &in_con.sin_addr, buffer, sizeof(buffer))) { fprintf(stderr, "%s: %s\n", program_name, strerror(errno)); exit(EXIT_FAILURE); } con->addr = strdup(buffer); if (!con->addr) { fprintf(stderr, "%s: %s\n", program_name, strerror(errno)); exit(EXIT_FAILURE); } } @ Here we start to negotiate the telnet options. We send the default options we want and set the key handler. @= { mat_printf(con, "%s" "%c%c%c" "%c%c%c" "%c%c%c" "%c%c%c" "%c%c%c", "-=> Please stand by . . .\r\n" "-=> Matanza is preparing your machine to maximize your experience . . . ", IAC, DO, TELOPT_TTYPE, IAC, DO, TELOPT_NAWS, IAC, DONT, TELOPT_LINEMODE, IAC, WILL, TELOPT_SGA, IAC, WILL, TELOPT_ECHO); mat_out_flush(con); } @ Please send me more names. @; menu->buflen[1] = 0; menu->buffer[1][0] = 0; menu->text_pos = 0; menu->text_cur = 0; menu->texterr = NULL; } @ |MAT_TEXTERR_BLANK| should have |MAT_TEXTERR_MAX| blanks. @d MAT_TEXTERR_MAX 29 @d MAT_TEXTERR_BLANK " " @
= void mat_mainmenu_key ( MatConnection *con, int input ) { MatStateMainMenu *menu; ASSERT(con->state == MAT_STATE_NORMAL); menu = con->anim_data; ASSERT(menu); ASSERT((menu->focus != 0 && menu->focus != 1) || menu->buflen[menu->focus] >= 0); menu->texterr = MAT_TEXTERR_BLANK; switch(menu->state) { case MENU_STATE_DATA: switch (input) { case 13: if (menu->focus == 3) { if (strlen(menu->buffer[0]) == 0) { menu->focus = 0; menu->texterr = "Enter a user name."; } else if (arg_password && strcmp(arg_password, menu->buffer[1])) { menu->buflen[1] = 0; menu->buffer[1][0] = 0; menu->focus = 1; menu->texterr = "Invalid password; try again."; } else { @; free(con->anim_data); con->anim_data = NULL; return; } } else do { menu->focus++; } while ((menu->focus == 1 && !arg_password) || (menu->focus == 2 && !arg_teams_count)); break; case 21: if (menu->focus == 0 || menu->focus == 1) { menu->buflen[menu->focus] = 0; menu->buffer[menu->focus][0] = 0; } break; case 27: menu->state = MENU_STATE_KEY; break; case 3: mat_connection_free(con, MMP_SERVER_CLOSE_CLIENT, "User quit."); return; case 127: case 8: if ((menu->focus == 0 || menu->focus == 1) && menu->buflen[menu->focus] > 0) { menu->buflen[menu->focus]--; menu->buffer[menu->focus][menu->buflen[menu->focus]] = 0; } break; default: if (menu->focus == 2) { switch(input) { case 'h': menu->team = menu->team->prev; if (!menu->team) menu->team = arg_teams_tail; break; case 'l': menu->team = menu->team->next; if (!menu->team) menu->team = arg_teams_head; break; } } else if (isalnum(input) && (isalpha(input) || menu->buflen[menu->focus] > 0) && (menu->focus != 0 || menu->buflen[0] < MAT_USER_MAX) && (menu->focus != 1 || menu->buflen[1] < MAT_PASSWORD_MAX) && menu->focus != 3) { menu->buffer[menu->focus][menu->buflen[menu->focus]++] = input; menu->buffer[menu->focus][menu->buflen[menu->focus]] = 0; } else VERBOSE("Invalid character: %d\n", input); break; } break; case MENU_STATE_KEY: if (input != 91) { VERBOSE("%s:%d: Unknown input: %d\n", __FILE__, __LINE__, input); menu->state = MENU_STATE_DATA; } else menu->state = MENU_STATE_KEYREAL; break; case MENU_STATE_KEYREAL: switch(input) { case 65: do { menu->focus--; } while ((menu->focus == 1 && !arg_password) || (menu->focus == 2 && !arg_teams_count)); if (menu->focus == -1) menu->focus = 3; break; case 66: do { menu->focus++; } while ((menu->focus == 1 && !arg_password) || (menu->focus == 2 && !arg_teams_count)); if (menu->focus == 4) menu->focus = 0; break; case 67: if (menu->focus == 2) { #if 0 p->info.player.team = p->info.player.team->prev; if (!p->info.player.team) p->info.player.team = arg_teams_tail; #endif } break; case 68: if (menu->focus == 2) { #if 0 p->info.player.team = p->info.player.team->next; if (!p->info.player.team) p->info.player.team = arg_teams_head; #endif } break; default: VERBOSE("%s:%d: Unknown input: %d\n", __FILE__, __LINE__, input); } menu->state = MENU_STATE_DATA; } @
; } @ @= { MatMovingObj *sh; int size_y; int slot = 0; size_y = con->ywinsize / con->ship_count; ASSERT(arg_imgwidth > 0); for (sh = con->ship_list; sh; sh = sh->info.player.conn_list_next) { ASSERT(sh->type == MAT_MOVING_OBJ_SHIP); sh->info.player.win_x_s = 0; sh->info.player.win_x_e = con->xwinsize; sh->info.player.imgwi = con->xwinsize * 2; sh->info.player.win_y_s = size_y * (slot + 0); sh->info.player.win_y_e = size_y * (slot + 1); sh->info.player.imghe = 2 * (sh->info.player.win_y_e - sh->info.player.win_y_s); ASSERT(sh->info.player.imgwi > 0); ASSERT(sh->info.player.imghe > 0); sh->info.player.world_wi = arg_imgwidth; sh->info.player.world_he = GET_WORLD_HE(sh->info.player, arg_imgwidth); ASSERT(sh->info.player.world_wi > 0); ASSERT(sh->info.player.world_he > 0); slot ++; } } @ @= { int slot; MatUniverse *un; con->graph_randomval = 60; ASSERT(arg_ppc > 0); MAT_UNIVERSES_FIND(un, 0); ASSERT(un); con->state = MAT_STATE_PLAYING; con->graph_randomval = 0; con->anim_func = draw_world; con->key_handler = arg_ppc == 1 ? player_input_default : player_input_multiple; con->ship_count = 0; @; MAT_SHIP_VIEW_CHECK(un); for (slot = 0; slot < arg_ppc; slot ++) @@; un->players_real += con->ship_count; MAT_SHIP_VIEW_CHECK(un); @; #if 0 YYYY if (p->info.player.team) { p->info.player.team_next = p->info.player.team->head; p->info.player.team->head = p; } #endif @; } @ @d GET_WORLD_HE(xpl, xwi) (int) ((double) xwi * CORRECTION * (double) (xpl).imghe / (double) (xpl).imgwi) @= { MatMovingObj *s; s = malloc(sizeof(MatMovingObj)); if (!s) { fprintf(stderr, "%s: %s\n", program_name, strerror(errno)); exit(EXIT_FAILURE); } s->type = MAT_MOVING_OBJ_SHIP; @; MAT_SHIP_VIEW_DEFAULT(s); s->refs = 1; s->img = mat_ship; s->draw = 1; s->un = un; ADD_MOVING_OBJ(s, un); s->rm_next = NULL; s->prevtype = NULL; s->nexttype = un->players_head; if (un->players_head) un->players_head->prevtype = s; else un->players_tail = s; un->players_head = s; strcpy(s->info.player.name, menu->buffer[0]); s->info.player.times_dead = 0; s->info.player.game_over = 0; s->info.player.chat_buffer_len = 0; s->info.player.chat_buffer[0] = 0; MAT_CONNECTION_SHIP_ADD(con, s); start_game(s); } @ @d MAT_SHIP_VIEW_DEFAULT(s) { s->info.player.view = s; s->info.player.viewers = s; s->info.player.view_next = s->info.player.view_prev = NULL; } @ @= { s->info.player.messages_start = 0; s->info.player.messages_count = 0; s->info.player.messages_pos = 0; s->info.player.messages_enabled = 1; } @ @d MAT_CONNECTION_SHIP_ADD(con, s) { int pos; s->info.player.conn = con; pos = con->ship_count % MAT_CONNECTION_SHIP_HASH_SIZE; s->info.player.conn_id = con->ship_count ++; s->info.player.conn_hash_next = con->ship_hash[pos]; s->info.player.conn_hash_prev = NULL; if (con->ship_hash[pos]) con->ship_hash[pos]->prev = s; con->ship_hash[pos] = s; s->info.player.conn_list_next = con->ship_list; s->info.player.conn_list_prev = NULL; if (con->ship_list) con->ship_list->prev = s; con->ship_list = s; } @ @
= { int p = 10; ASSERT(menu); mat_print(con, 10, p, menu->focus == 0 ? MAT_RED_BOLD : MAT_RED, "User:", 0); mat_print(con, 21, p, MAT_BLUE, menu->focus == 0 ? "-=> [" : " [", 0); mat_print(con, 28 + MAT_USER_MAX, p, MAT_BLUE, menu->focus == 0 ? "] <=-" : "] ", 0); mat_print(con, 27, p, MAT_NORMAL, MAT_USER_BLANK, 0); mat_print(con, 27, p, MAT_NORMAL, menu->buffer[0], 0); mat_flush(con, 10, p, 33 + MAT_USER_MAX, p + 1); p += 2; if (arg_password) { mat_print(con, 10, p, menu->focus == 1 ? MAT_RED_BOLD : MAT_RED, "Password:", 0); mat_print(con, 21, p, MAT_BLUE, menu->focus == 1 ? "-=> [" : " [", 0); mat_print(con, 28 + MAT_PASSWORD_MAX, p, MAT_BLUE, menu->focus == 1 ? "] <=-" : "] ", 0); mat_print(con, 27, p, MAT_NORMAL, MAT_PASSWORD_BLANK, 0); mat_print(con, 27, p, MAT_NORMAL, menu->buffer[1], 0); mat_flush(con, 10, p, 33 + MAT_USER_MAX, p + 1); p += 2; } if (arg_teams_count) { #if 0 YYYYY ASSERT(con->ship->info.player.team); ASSERT(con->ship->info.player.team->name); mat_print(&p->info.player, 10, pos, menu->focus == 2 ? MAT_RED_BOLD : MAT_RED, "Team:"); mat_print(&p->info.player, 21, pos, MAT_BLUE, menu->focus == 2 ? "-=> [" : " ["); mat_print(&p->info.player, 28 + MAT_TEAM_MAX, pos, MAT_BLUE, menu->focus == 2 ? "] <=-" : "] "); mat_print(&p->info.player, 27, pos, MAT_NORMAL, MAT_TEAM_BLANK); mat_print(&p->info.player, 27, pos, MAT_NORMAL, p->info.player.team->name); mat_flush(p, 10, pos, 33 + MAT_TEAM_MAX, pos + 1); pos += 2; #endif } if (menu->texterr) { ASSERT(strlen(menu->texterr) < MAT_TEXTERR_MAX); mat_print(con, 10, p, MAT_RED_BOLD, menu->texterr, 0); mat_flush(con, 10, p, 8 + MAT_TEXTERR_MAX, p + 1); } } @ @
= void mat_mainmenu_anim ( MatConnection *con ) { static char *text[] = { "Welcome to Matanga... ", NULL }; ASSERT(con); mat_print(con, MAX(con->xwinsize - DATAMENU(text_pos) - 1, 0), con->ywinsize - 1, MAT_BOLD, text[DATAMENU(text_cur)] + MAX(DATAMENU(text_pos) - con->xwinsize + 1, 0), 0); mat_flush(con, 0, con->ywinsize - 1, con->xwinsize, con->ywinsize); if (text[DATAMENU(text_cur)][MAX(DATAMENU(text_pos) - con->xwinsize, 0)] == 0) { DATAMENU(text_pos) = 0; DATAMENU(text_cur) ++; if (!text[DATAMENU(text_cur)]) DATAMENU(text_cur) = 0; } else DATAMENU(text_pos++); } @ Now we check to see if connection |con| is a machine or a player and call the appropriate macro. @= { if (con->state == MAT_STATE_MACHINE) @@; else @@; } @ @= { int i; ASSERT(con); for (i = con->bufprc; i < con->buflen && con->state != MAT_STATE_REMOVE; i++) if (con->key_handler) { /* VERBOSE("Got: %d (%c) [%d]\n", *(con->buffer + i), *(con->buffer + i), i); */ con->key_handler(con, *(con->buffer + i)); } memmove(con->buffer, con->buffer + i, con->buflen - i); con->buflen -= i; con->bufprc = 0; } @ The actual processing for every character in the input buffer depends on the player's state. We will call the player's |key_handler| for every character on his buffer. After this is done, we remove the bytes from the buffer. @d MAT_KEY_DATA 0 @d MAT_KEY_IAC 1 @d MAT_KEY_WILL 2 @d MAT_KEY_WONT 3 @d MAT_KEY_DO 4 @d MAT_KEY_DONT 5 @d MAT_KEY_SB 6 @d MAT_KEY_SE 7 @d MAT_KEY_27 8 @d MAT_KEY_79 9 @d MAT_KEY_91 10 @d KEY_ARROW_UP -10 @d KEY_ARROW_DOWN -11 @d KEY_ARROW_RIGHT -12 @d KEY_ARROW_LEFT -13 @d GOT_INPUT(con, c) if (con->key_handler) con->key_handler(con, c); @= { int i, c; ASSERT(con); for (i = con->bufprc; i < con->buflen; i++) { c = *(con->buffer + i) & 0377; switch (con->input_state) { case MAT_KEY_DATA: switch (c) { case IAC: con->input_state = MAT_KEY_IAC; break; case 27: con->input_state = MAT_KEY_27; break; case 0: break; default: GOT_INPUT(con, c); } break; case MAT_KEY_IAC: switch(c) { case WILL: con->input_state = MAT_KEY_WILL; break; case WONT: con->input_state = MAT_KEY_WONT; break; case DO: con->input_state = MAT_KEY_DO; break; case DONT: con->input_state = MAT_KEY_DONT; break; case IAC: break; case IP: if (con->state == MAT_STATE_PLAYING) MESSAGE_FROM(con, "has left for the real world.") mat_connection_free(con, MMP_SERVER_CLOSE_CLIENT, "User interrupt."); break; case BREAK: VERBOSE("Got IAC BREAK\n"); break; case AYT: VERBOSE("Got IAC AYT\n"); break; case AO: VERBOSE("Got IAC AO\n"); break; case SB: con->input_state = MAT_KEY_SB; con->telnet_args = i + 1; break; default: VERBOSE("Ignored Input: [key:%d][state:%d]\n", c, con->input_state); con->input_state = MAT_KEY_DATA; } break; case MAT_KEY_27: switch (c) { case 79: con->input_state = MAT_KEY_79; break; case 91: con->input_state = MAT_KEY_91; break; default: con->input_state = MAT_KEY_DATA; VERBOSE("Ignored Input: [key:%d][state:%d]\n", c, con->input_state); } break; case MAT_KEY_79: case MAT_KEY_91: switch(c) { case 65: GOT_INPUT(con, KEY_ARROW_UP); break; case 66: GOT_INPUT(con, KEY_ARROW_DOWN); break; case 67: GOT_INPUT(con, KEY_ARROW_RIGHT); break; case 68: GOT_INPUT(con, KEY_ARROW_LEFT); break; default: VERBOSE("Ignored Input: [key:%d][state:%d]\n", c, con->input_state); } con->input_state = MAT_KEY_DATA; break; case MAT_KEY_SB: if (c == IAC) con->input_state = MAT_KEY_SE; break; case MAT_KEY_SE: @; break; case MAT_KEY_WILL: @; con->input_state = MAT_KEY_DATA; break; case MAT_KEY_WONT: @; con->input_state = MAT_KEY_DATA; break; case MAT_KEY_DO: @; con->input_state = MAT_KEY_DATA; break; case MAT_KEY_DONT: @; con->input_state = MAT_KEY_DATA; break; default: ASSERT(0); } } memmove(con->buffer, con->buffer + i, con->buflen - i); con->buflen -= i; con->bufprc = 0; } @ @= { MatMovingObj *tmp; while (con->ship_list) { @; con->ship_list->info.player.conn = NULL; tmp = con->ship_list->info.player.conn_list_next; mat_moving_obj_unref(con->ship_list); con->ship_list = tmp; } } @ @= { MatUniverse *un; MatSub *c; char *name; name = con->ship_list->info.player.name; un = con->ship_list->un; for (c = un->subs; c; c = c->u_next) mat_printf(c->m, "%c%c%c%s%c", MMP_SERVER_DEFAULT_SHIPRM, un->id & 0xff00, un->id & 0x00ff, name, 0); } @ Now we will add a function to remove a player. It doesn't actually remove it from the list because that may mess up things for the caller. It sets its |state| to |MAT_STATE_REMOVE| so it gets removed eventually. @= void mat_connection_free ( MatConnection *con, unsigned char reason, char *desc ) { ASSERT(con->state != MAT_STATE_REMOVE); if (con->state == MAT_STATE_PLAYING || con->state == MAT_STATE_MACHINE) @; if (con->state != MAT_STATE_MACHINE) { @; free(con->buffer); mat_printf(con, "You have been disconnected from the server.\r\nReason: %s\r\n\r\n" "Thanks for playing Matanza.\r\n" "FU Matanza %s\r\n%s\r\n", desc, VERSION, "Copyright 2000 Alejandro Forero Cuervo"); } else { mat_sub_machine_rm(con); mat_printf(con, "%c%c", MMP_SERVER_CLOSE, reason); if (reason == MMP_SERVER_CLOSE_SYSERROR || reason == MMP_SERVER_CLOSE_MMPERROR) mat_printf(con, "%s%c", desc, 0); } mat_out_flush(con); con->state = MAT_STATE_REMOVE; free(con->addr); free(con->out_buf); free(con->anim_data); SOCKET_CLOSE_GENERIC(con->fd); } @ @= void mat_connection_free ( MatConnection *, unsigned char, char * ); @ @= { int xspeed, rspeed; //if (his_state_is_wont(TELOPT_TSPEED)) // break; ASSERT(con->buflen > con->telnet_args); if ((con->buffer[con->telnet_args++] & 0xff) != TELQUAL_IS) ASSERT(0); /* TODO: Just kill this player. */ xspeed = atoi(con->buffer + con->telnet_args); while (con->buffer[con->telnet_args] != ',' && con->buflen > con->telnet_args) con->telnet_args++; ASSERT(con->buflen > con->telnet_args); rspeed = atoi(con->buffer + con->telnet_args); VERBOSE("Ignoring TSPEED: %d %d\n", xspeed, rspeed); } @ @= { int j; //if (his_state_is_wont(TELOPT_TTYPE)) /* Ignore if option disabled */ // break; ASSERT(con->buflen > con->telnet_args); if ((con->buffer[con->telnet_args++] & 0xff) != TELQUAL_IS) ASSERT(1); /* TODO: Just kill this player. */ for (j = 0; j < 14 && con->telnet_args + 1 < i; j ++, con->telnet_args++) con->terminal_name[j] = tolower(con->buffer[con->telnet_args]); con->terminal_name[j] = 0; VERBOSE("Got terminal name: %s\n", con->terminal_name); } @ @= { ASSERT(con->buflen > con->telnet_args); con->telnet_args++; ASSERT(con->buflen > con->telnet_args); if ((con->buffer[con->telnet_args] & 0xff) == LM_SLC) { VERBOSE("Disabling TELOPT_LINEMODE for player.\n"); mat_printf(con, "%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE, LM_SLC, IAC, SE); } else if (con->buffer[con->telnet_args] == LM_MODE) { VERBOSE("Use edit mode: %d\n", con->buffer[con->telnet_args++]); } else { ASSERT(con->buflen > con->telnet_args); VERBOSE("Telnet: Invalid char received in TELOPT_LINEMODE: %s:%d\n", __FILE__, __LINE__); } } @ @= { int width, height; //if (his_state_is_wont(TELOPT_NAWS)) /* Ignore if option disabled */ // break; ASSERT(con->buflen > con->telnet_args); width = (con->buffer[con->telnet_args++] & 0xff) << 8; ASSERT(con->buflen > con->telnet_args); width |= (con->buffer[con->telnet_args++] & 0xff); ASSERT(con->buflen > con->telnet_args); height = (con->buffer[con->telnet_args++] & 0xff) << 8; ASSERT(con->buflen > con->telnet_args); height |= (con->buffer[con->telnet_args++] & 0xff); VERBOSE("Got window size: %d x %d\n", width, height); if (width > 0 && height > 0) mat_graph_resize(con, width, height); } @ @= if (c != SE) { ASSERT(c == IAC); con->input_state = MAT_KEY_IAC; } else { switch (con->buffer[con->telnet_args++]) { case TELOPT_TSPEED: @; break; case TELOPT_TTYPE: @; break; case TELOPT_NAWS: @; break; case TELOPT_LINEMODE: @; break; default: VERBOSE("Unknown telnet parameter: %d\n", con->buffer[con->telnet_args - 1]); break; } con->input_state = MAT_KEY_DATA; check_telnet_negotiation(con); } @ @= { VERBOSE("Telnet: Got DONT %d\n", c); @; } @ @= { ASSERT(con); switch (c) { case TELOPT_LOGOUT: @; if (con->state == MAT_STATE_PLAYING) MESSAGE_FROM(con, "has left for the real world"); mat_connection_free(con, MMP_SERVER_CLOSE_CLIENT, "User logout."); break; case TELOPT_ECHO: VERBOSE("Telnet: Got DO ECHO\n"); break; case TELOPT_SGA: VERBOSE("Telnet: Got DO SGA\n"); @; break; default: VERBOSE("Telnet: Got DO %d\n", c); @; } } @ @= { ASSERT(con); switch (c) { case TELOPT_TSPEED: case TELOPT_TTYPE: case TELOPT_NAWS: mat_printf(con, "%c%c%c%c%c%c", IAC, SB, c, TELQUAL_SEND, IAC, SE); mat_out_flush(con); break; case TELOPT_LINEMODE: VERBOSE("Telnet: Player TELOPT_LINEMODE\n"); break; default: VERBOSE("Telnet: Got WILL %d\n", c); @; } } @ @= { ASSERT(con); switch (c) { case TELOPT_TTYPE: strcpy(con->terminal_name, "dumb"); check_telnet_negotiation(con); break; case TELOPT_NAWS: mat_graph_resize(con, 80, 24); check_telnet_negotiation(con); break; case TELOPT_ECHO: VERBOSE("Telnet: Client won't echo\n"); @; break; case TELOPT_LINEMODE: VERBOSE("Telnet: Client won't do linemode (may do buffering)\n"); break; default: @; VERBOSE("Telnet: Got WONT %d\n", c); } } @ @= { ASSERT(con); mat_printf(con, "%c%c%c", IAC, WILL, c); mat_out_flush(con); } @ @= { ASSERT(con); mat_printf(con, "%c%c%c", IAC, WONT, c); mat_out_flush(con); } @ @= { ASSERT(con); mat_printf(con, "%c%c%c", IAC, DONT, c); mat_out_flush(con); } @ @= { ASSERT(con); mat_printf(con, "%c%c%c", IAC, DO, c); mat_out_flush(con); } @ The following values are used to generate the palette used to draw fire. @= static int fire_pal[] = { 0, 0, 0, 0, 0, 6, 0, 0, 6, 0, 0, 7, 0, 0, 8, 0, 0, 8, 0, 0, 9, 0, 0, 10, 2, 0, 10, 4, 0, 9, 6, 0, 9, 8, 0, 8, 10, 0, 7, 12, 0, 7, 14, 0, 6, 16, 0, 5, 18, 0, 5, 20, 0, 4, 22, 0, 4, 24, 0, 3, 26, 0, 2, 28, 0, 2, 30, 0, 1, 32, 0, 0, 32, 0, 0, 33, 0, 0, 34, 0, 0, 35, 0, 0, 36, 0, 0, 36, 0, 0, 37, 0, 0, 38, 0, 0, 39, 0, 0, 40, 0, 0, 40, 0, 0, 41, 0, 0, 42, 0, 0, 43, 0, 0, 44, 0, 0, 45, 0, 0, 46, 1, 0, 47, 1, 0, 48, 2, 0, 49, 2, 0, 50, 3, 0, 51, 3, 0, 52, 4, 0, 53, 4, 0, 54, 5, 0, 55, 5, 0, 56, 6, 0, 57, 6, 0, 58, 7, 0, 59, 7, 0, 60, 8, 0, 61, 8, 0, 63, 9, 0, 63, 9, 0, 63, 10, 0, 63, 10, 0, 63, 11, 0, 63, 11, 0, 63, 12, 0, 63, 12, 0, 63, 13, 0, 63, 13, 0, 63, 14, 0, 63, 14, 0, 63, 15, 0, 63, 15, 0, 63, 16, 0, 63, 16, 0, 63, 17, 0, 63, 17, 0, 63, 18, 0, 63, 18, 0, 63, 19, 0, 63, 19, 0, 63, 20, 0, 63, 20, 0, 63, 21, 0, 63, 21, 0, 63, 22, 0, 63, 22, 0, 63, 23, 0, 63, 24, 0, 63, 24, 0, 63, 25, 0, 63, 25, 0, 63, 26, 0, 63, 26, 0, 63, 27, 0, 63, 27, 0, 63, 28, 0, 63, 28, 0, 63, 29, 0, 63, 29, 0, 63, 30, 0, 63, 30, 0, 63, 31, 0, 63, 31, 0, 63, 32, 0, 63, 32, 0, 63, 33, 0, 63, 33, 0, 63, 34, 0, 63, 34, 0, 63, 35, 0, 63, 35, 0, 63, 36, 0, 63, 36, 0, 63, 37, 0, 63, 38, 0, 63, 38, 0, 63, 39, 0, 63, 39, 0, 63, 40, 0, 63, 40, 0, 63, 41, 0, 63, 41, 0, 63, 42, 0, 63, 42, 0, 63, 43, 0, 63, 43, 0, 63, 44, 0, 63, 44, 0, 63, 45, 0, 63, 45, 0, 63, 46, 0, 63, 46, 0, 63, 47, 0, 63, 47, 0, 63, 48, 0, 63, 48, 0, 63, 49, 0, 63, 49, 0, 63, 50, 0, 63, 50, 0, 63, 51, 0, 63, 52, 0, 63, 52, 0, 63, 52, 0, 63, 52, 0, 63, 52, 0, 63, 53, 0, 63, 53, 0, 63, 53, 0, 63, 53, 0, 63, 54, 0, 63, 54, 0, 63, 54, 0, 63, 54, 0, 63, 54, 0, 63, 55, 0, 63, 55, 0, 63, 55, 0, 63, 55, 0, 63, 56, 0, 63, 56, 0, 63, 56, 0, 63, 56, 0, 63, 57, 0, 63, 57, 0, 63, 57, 0, 63, 57, 0, 63, 57, 0, 63, 58, 0, 63, 58, 0, 63, 58, 0, 63, 58, 0, 63, 59, 0, 63, 59, 0, 63, 59, 0, 63, 59, 0, 63, 60, 0, 63, 60, 0, 63, 60, 0, 63, 60, 0, 63, 60, 0, 63, 61, 0, 63, 61, 0, 63, 61, 0, 63, 61, 0, 63, 62, 0, 63, 62, 0, 63, 62, 0, 63, 62, 0, 63, 63, 0, 63, 63, 1, 63, 63, 2, 63, 63, 3, 63, 63, 4, 63, 63, 5, 63, 63, 6, 63, 63, 7, 63, 63, 8, 63, 63, 9, 63, 63, 10, 63, 63, 10, 63, 63, 11, 63, 63, 12, 63, 63, 13, 63, 63, 14, 63, 63, 15, 63, 63, 16, 63, 63, 17, 63, 63, 18, 63, 63, 19, 63, 63, 20, 63, 63, 21, 63, 63, 21, 63, 63, 22, 63, 63, 23, 63, 63, 24, 63, 63, 25, 63, 63, 26, 63, 63, 27, 63, 63, 28, 63, 63, 29, 63, 63, 30, 63, 63, 31, 63, 63, 31, 63, 63, 32, 63, 63, 33, 63, 63, 34, 63, 63, 35, 63, 63, 36, 63, 63, 37, 63, 63, 38, 63, 63, 39, 63, 63, 40, 63, 63, 41, 63, 63, 42, 63, 63, 42, 63, 63, 43, 63, 63, 44, 63, 63, 45, 63, 63, 46, 63, 63, 47, 63, 63, 48, 63, 63, 49, 63, 63, 50, 63, 63, 51, 63, 63, 52, 63, 63, 52, 63, 63, 53, 63, 63, 54, 63, 63, 55, 63, 63, 56, 63, 63, 57, 63, 63, 58, 63, 63, 59, 63, 63, 60, 63, 63, 61, 63, 63, 62, 63, 63, 63 }; int fire_palette[256]; @ Now some mechanisms for assertions. The function assert_exit is used so you can have your debugger stop execution when an assertion fails. @= #if MATANZA_ASSERT #define ASSERT(x) \ if(!(x)) \ fprintf(stderr, "%s:%d: ASSERT failed\n", __FILE__, __LINE__), assert_exit() #define ASSERT_FOR(x) for(x) #else #define ASSERT(x) #define ASSERT_FOR(x) #endif @ @= #if MATANZA_ASSERT void assert_exit ( void ) { exit(-1); } #endif @ To get rid of the current verbosity, define VERBOSE to empty. Matanza might then throw a lot of warnings during compilation, but will work. @= #if MATANZA_VERBOSE #define VERBOSE if (arg_verbose) printf int arg_verbose = 0; #else #define VERBOSE #endif @ @= void assert_exit ( void ); @ Lets include all the files we can. We should check this and make sure it really is what we want. @= #include #include #include #include #include #include #include #include #include #include #include /* Headers for Windows */ #if HAVE_WINSOCK2_H #include #endif #if HAVE_WINDOWS_H #include #endif #if HAVE_DIRECT_H #include #endif /* Headers for BeOS */ #if HAVE_OS_H #include #endif #if HAVE_ERRORS_H #include #endif /* Headers for Unix */ #if HAVE_NETDB_H #include #endif #if HAVE_UNISTD_H #include #endif #if HAVE_NETINET_IN_H #include #endif #if HAVE_ARPA_INET_H #include #endif #if HAVE_SYS_IOCTL_H #include #endif #if HAVE_SYS_TIME_H #include #endif #if HAVE_SYS_TYPES_H #include #endif #if HAVE_SYS_SOCKET_H #include #endif #ifdef HAVE_ARPA_TELNET_H #include #else @@; #endif /* The following files are bundled with Matanza. If you get errors with * the following lines, make sure you have the directory where your Matanza * source code resides as part of your standard includes (for gcc, this is * specified using the parameter -I). */ #include #include #include #include @ @= #define SE 240 /* end sub negotiation */ #define BREAK 243 /* break */ #define IP 244 /* interrupt process--permanently */ #define AO 245 /* abort output--but let prog finish */ #define AYT 246 /* are you there */ #define SB 250 /* interpret as subnegotiation */ #define WILL 251 /* I will use option */ #define WONT 252 /* I won't use option */ #define DO 253 /* please, you use option */ #define DONT 254 /* you are not to use option */ #define IAC 255 /* interpret as command: */ #define TELOPT_ECHO 1 /* echo */ #define TELOPT_SGA 3 /* suppress go ahead */ #define TELOPT_LOGOUT 18 /* force logout */ #define TELOPT_TTYPE 24 /* terminal type */ #define TELOPT_NAWS 31 /* window size */ #define TELOPT_TSPEED 32 /* terminal speed */ #define TELOPT_LINEMODE 34 /* Linemode option */ #define LM_MODE 1 #define LM_SLC 3 #define TELQUAL_IS 0 /* option is... */ #define TELQUAL_SEND 1 /* send option */ @ @= struct MatImage { int h, w; unsigned char *img; /* Color (0 = black, 255 = white) */ }; @ And we also need one struct to keep count of the bullets. |angle_x| and |angle_y| are always greater or equal than zero, and |dir_x| and |dir_y| are used to know if the bullet is headed left or right and up or down. If |img| is |NULL|, the image is a point. @= typedef struct MatBullet MatBullet; struct MatBullet { int expires; int bright; MatMovingObj *src; int type; }; @ @d MAP_EMPTY; @= MatImage *mat_ship; unsigned char *mat_ship_palette[3]; MatImage *mat_ast [2]; MatImage *mat_missile [3]; @ @= int mat_bullets_damage [4] = { 15, 100, 400, 3000 }; double mat_bullets_speed [4] = { 8.0 / STEPS_MOVEMENT, 11.0 / STEPS_MOVEMENT, 14.5 / STEPS_MOVEMENT, 8.0 / STEPS_MOVEMENT }; int mat_bullets_back [4] = { 1, 0, 0, 0 }; int mat_bullets_bexp [4] = { 20, 40, 200, 3000 }; int mat_bullets_pexp [4] = { 1, 3, 6, 10 }; char *mat_bullets_name [4] = { "bullets", "small missiles", "missiles", "torpedoes" }; char *mat_bullets_hit [4] = { "-=> You got %s !", "-=> Your small missile got %s !", "-=> Bang, your missile got %s !", "-=> BOOM, your torpedo got %s !" }; char *mat_bullets_hit_ast [4] = { "-=> You reached the asteroid !", "-=> Your small missile reached the asteroid !", "-=> Bang, your missile hit the asteroid !", "-=> BOOM, your torpedo got the asteroid !" }; @ @= { int i; if (arg_ast_num > 0) { for (i = 0; i < arg_ang; i ++) { free(mat_ast[0][i].img); free(mat_ast[1][i].img); } free(mat_ast[0]); free(mat_ast[1]); } } @ @d POS_AST(j,i) (int)(j + MAT_AST_SIZE_Y / 2) * MAT_AST_SIZE_X + (int)(i + MAT_AST_SIZE_X / 2) @= { int i, j, ang; double x, y, c, s; if (arg_ast_num > 0) { VERBOSE("Calculating rotations of asteroids... "); fflush(stdout); mat_ast[0] = malloc(sizeof(MatImage) * arg_ang); mat_ast[1] = malloc(sizeof(MatImage) * arg_ang); if (!mat_ast[0] || !mat_ast[1]) { fprintf(stderr, "%s: %s\n", program_name, strerror(errno)); exit(EXIT_FAILURE); } for (ang = 0; ang < arg_ang; ang ++) { c = mat_cos[ang]; s = mat_sin[ang]; mat_ast[0][ang].w = MAT_AST_SIZE_X; mat_ast[1][ang].w = MAT_AST_SIZE_X; mat_ast[0][ang].h = MAT_AST_SIZE_Y; mat_ast[1][ang].h = MAT_AST_SIZE_Y; mat_ast[0][ang].img = malloc(MAT_AST_SIZE_X * MAT_AST_SIZE_Y); mat_ast[1][ang].img = malloc(MAT_AST_SIZE_X * MAT_AST_SIZE_Y); if (!mat_ast[0][ang].img || !mat_ast[1][ang].img) { fprintf(stderr, "%s: %s\n", program_name, strerror(errno)); exit(EXIT_FAILURE); } for (j = -MAT_AST_SIZE_Y / 2; j * 2 < MAT_AST_SIZE_Y; j ++) for (i = -MAT_AST_SIZE_X / 2; i * 2 < MAT_AST_SIZE_X; i ++) { x = i * c - j * s; y = i * s + j * c; if ( x < -MAT_AST_SIZE_X / 2 || x > MAT_AST_SIZE_X / 2 || y < -MAT_AST_SIZE_Y / 2 || y > MAT_AST_SIZE_Y / 2 ) { mat_ast[0][ang].img[POS_AST(j,i)] = ' '; mat_ast[1][ang].img[POS_AST(j,i)] = ' '; } else { mat_ast[0][ang].img[POS_AST(j,i)] = mat_graph_ast[0][POS_AST(y,x)]; mat_ast[1][ang].img[POS_AST(j,i)] = mat_graph_ast[1][POS_AST(y,x)]; } } } VERBOSE("Done\nOptimizing images for the asteroids... [%dx%d] [%dx%d]", mat_ast[0][0].h, mat_ast[0][0].w, mat_ast[1][0].h, mat_ast[1][0].w); fflush(stdout); mat_image_optimize(mat_ast[0]); mat_image_optimize(mat_ast[1]); VERBOSE(" -> [%dx%d] [%dx%d]\n", mat_ast[0][0].h, mat_ast[0][0].w, mat_ast[1][0].h, mat_ast[1][0].w); } } @ @= { int i; if (arg_ast_num > 0) { for (i = 0; i < arg_ang; i ++) { free(mat_missile[0][i].img); free(mat_missile[1][i].img); free(mat_missile[2][i].img); } free(mat_missile[0]); free(mat_missile[1]); free(mat_missile[2]); } } @ @d POS_MISSILE(j,i) (int)(j + MAT_MISSILESIZE_Y / 2) * MAT_MISSILESIZE_X + (int)(i + MAT_MISSILESIZE_X / 2) @= { int i, j, ang; double x, y, c, s; VERBOSE("Calculating rotations of missiles... "); fflush(stdout); mat_missile[0] = malloc(sizeof(MatImage) * arg_ang); mat_missile[1] = malloc(sizeof(MatImage) * arg_ang); mat_missile[2] = malloc(sizeof(MatImage) * arg_ang); if (!mat_missile[0] || !mat_missile[1] || !mat_missile[2]) { fprintf(stderr, "%s: %s\n", program_name, strerror(errno)); exit(EXIT_FAILURE); } for (ang = 0; ang < arg_ang; ang ++) { c = mat_cos[ang]; s = mat_sin[ang]; mat_missile[0][ang].w = MAT_MISSILESIZE_X; mat_missile[1][ang].w = MAT_MISSILESIZE_X; mat_missile[2][ang].w = MAT_MISSILESIZE_X; mat_missile[0][ang].h = MAT_MISSILESIZE_Y; mat_missile[1][ang].h = MAT_MISSILESIZE_Y; mat_missile[2][ang].h = MAT_MISSILESIZE_Y; mat_missile[0][ang].img = malloc(MAT_MISSILESIZE_X * MAT_MISSILESIZE_Y); mat_missile[1][ang].img = malloc(MAT_MISSILESIZE_X * MAT_MISSILESIZE_Y); mat_missile[2][ang].img = malloc(MAT_MISSILESIZE_X * MAT_MISSILESIZE_Y); if (!mat_missile[0][ang].img || !mat_missile[1][ang].img || !mat_missile[2][ang].img) { fprintf(stderr, "%s: %s\n", program_name, strerror(errno)); exit(EXIT_FAILURE); } for (j = -MAT_MISSILESIZE_Y / 2; j * 2 < MAT_MISSILESIZE_Y; j ++) for (i = -MAT_MISSILESIZE_X / 2; i * 2 < MAT_MISSILESIZE_X; i ++) { x = i * c - j * s; y = i * s + j * c; if ( x < -MAT_MISSILESIZE_X / 2 || x > MAT_MISSILESIZE_X / 2 || y < -MAT_MISSILESIZE_Y / 2 || y > MAT_MISSILESIZE_Y / 2 ) { mat_missile[0][ang].img[POS_MISSILE(j,i)] = ' '; mat_missile[1][ang].img[POS_MISSILE(j,i)] = ' '; mat_missile[2][ang].img[POS_MISSILE(j,i)] = ' '; } else { mat_missile[0][ang].img[POS_MISSILE(j,i)] = mat_graph_missile[0][POS_MISSILE(y,x)]; mat_missile[1][ang].img[POS_MISSILE(j,i)] = mat_graph_missile[1][POS_MISSILE(y,x)]; mat_missile[2][ang].img[POS_MISSILE(j,i)] = mat_graph_missile[2][POS_MISSILE(y,x)]; } } } VERBOSE("Done\nOptimizing images for [%dx%d] [%dx%d] [%dx%d]", mat_missile[0][0].h, mat_missile[0][0].w, mat_missile[1][0].h, mat_missile[1][0].w, mat_missile[2][0].h, mat_missile[2][0].w); fflush(stdout); mat_image_optimize(mat_missile[0]); mat_image_optimize(mat_missile[1]); mat_image_optimize(mat_missile[2]); VERBOSE(" -> [%dx%d] [%dx%d] [%dx%d]\n", mat_missile[0][0].h, mat_missile[0][0].w, mat_missile[1][0].h, mat_missile[1][0].w, mat_missile[2][0].h, mat_missile[2][0].w); } @ Here we rotate the matrix for the ships. @d ANGLE_SPEED_MAX 1 @d PI 3.141592 @d POS_SHIP(j,i) (int)(j + size / 2) * size + (int)(i + size / 2) @d POS_SHIP_ORIGINAL(j,i) (int)(j + MAT_SHIPSIZE_Y / 2) * MAT_SHIPSIZE_X + (int)(i + MAT_SHIPSIZE_X / 2) @= { int i, j, ang, size; VERBOSE("Calculating rotations of ships... "); fflush(stdout); mat_ship = malloc(sizeof(MatImage) * arg_ang); if (!mat_ship) { fprintf(stderr, "%s: %s\n", program_name, strerror(errno)); exit(EXIT_FAILURE); } size = (int) sqrt(MAT_SHIPSIZE_X * MAT_SHIPSIZE_X + MAT_SHIPSIZE_Y * MAT_SHIPSIZE_Y) + 1; for (ang = 0; ang < arg_ang; ang ++) { double c, s; c = mat_cos[ang]; s = mat_sin[ang]; mat_ship[ang].w = size; mat_ship[ang].h = size; mat_ship[ang].img = malloc(mat_ship[ang].w * mat_ship[ang].h); if (!mat_ship[ang].img) { fprintf(stderr, "%s: %s\n", program_name, strerror(errno)); exit(EXIT_FAILURE); } for (j = - size / 2; j < size / 2; j ++) for (i = - size / 2; i < size / 2; i ++) { double x, y; x = i * c - j * s; y = i * s + j * c; ASSERT(0 <= POS_SHIP(j, i)); ASSERT(POS_SHIP(j, i) < mat_ship[ang].w * mat_ship[ang].h); if ( (int) x < -MAT_SHIPSIZE_X / 2 || (int) x >= MAT_SHIPSIZE_X / 2 || (int) y < -MAT_SHIPSIZE_Y / 2 || (int) y >= MAT_SHIPSIZE_Y / 2 ) { mat_ship[ang].img[POS_SHIP(j, i)] = ' '; } else { ASSERT((int) y + MAT_SHIPSIZE_Y / 2 < MAT_SHIPSIZE_Y); ASSERT((int) x + MAT_SHIPSIZE_X / 2 < MAT_SHIPSIZE_X); ASSERT(0 <= POS_SHIP_ORIGINAL(y, x)); ASSERT(POS_SHIP_ORIGINAL(y, x) < MAT_SHIPSIZE_X * MAT_SHIPSIZE_Y); mat_ship[ang].img[POS_SHIP(j, i)] = arg_ship_graphic[POS_SHIP_ORIGINAL(y,x)]; } } } VERBOSE("Done\nOptimizing images for the ships... [%dx%d]", mat_ship[0].h, mat_ship[0].w); fflush(stdout); mat_image_optimize(mat_ship); VERBOSE(" -> [%dx%d]\n", mat_ship[0].h, mat_ship[0].w); } @ @= { int i; if (arg_ast_num > 0) { for (i = 0; i < arg_ang; i ++) { free(mat_ship[i].img); } free(mat_ship); } } @ A function to set up a player in the game. This is called whenever he is about to begin a new life. @= void start_game ( MatMovingObj *ship ) { ASSERT(ship); ASSERT(ship->type == MAT_MOVING_OBJ_SHIP); ASSERT(ship->un); ship->crash = 0; ship->alpha = 0.0; ship->alpha_mod = mat_alpha_mod_ship_appear; @; @; ship->info.player.visible = 1; ship->info.player.visible_exp = arg_visible_init; ship->info.player.health = ship->un->health; ship->info.player.ship_speed_inc = 0; ship->pal = mat_ship_palette[2]; } @ @= { ship->info.player.ship_bullets[0] = 20000; ship->info.player.ship_bullets[1] = 7; ship->info.player.ship_bullets[2] = 2; ship->info.player.ship_bullets[3] = 0; ship->info.player.bullets_expire = 0; } @ @d MESSAGE_TO(con, msg) { MatMovingObj *sh; for (sh = con->ship_list; sh; sh = sh->info.player.conn_list_next) sprintf(message_get(sh), msg); } @ @= { MatMovingObj *sh; ASSERT(con->state == MAT_STATE_PLAYING); for (sh = con->ship_list; sh; sh = sh->info.player.conn_list_next) { ASSERT(sh->type == MAT_MOVING_OBJ_SHIP); ASSERT(sh->un->players_real >= 1); if (sh->un->players_real == 1) sprintf(message_get(sh), "-=> You are all alone . . ."); else { MatSub *i; MESSAGE_FROM_IP(con, "joins the game"); sprintf(message_get(sh), "-=> There are %d ships in this universe.", sh->un->players_real); for (i = sh->un->subs; i; i = i->u_next) mat_printf(i->m, "%c%c%c%s%c", MMP_SERVER_DEFAULT_SHIPADD_OTHER, 0, 0, sh->info.player.name, 0); } if (un->pause) MESSAGE_TO(con, "-=> Time is frozen . . ."); } } @ @= void player_input_buffer ( MatConnection *con, int key ) { ASSERT(con); ASSERT(con->state == MAT_STATE_PLAYING); ASSERT(con->ship_count == 1); switch(key) { case 13: ship_key_chat_end(con); break; case 21: ship_key_chat_wipe(con->ship_list); break; case 127: case 8: ship_key_chat_backspace(con->ship_list); break; default: ship_key_chat_add(con->ship_list, key); break; } } @ Now a function for a very simple state. When the player hits `q', he enters the `quit' state that this function handles... Basically, he gets asked for confirmation. If he enters `y' or `q', he quits. Otherwise, he is allowed to continue playing. @= void player_input_quit ( MatConnection *con, int key ) { ASSERT(con->state == MAT_STATE_PLAYING); switch (tolower(key)) { case 'q': case 'y': ship_key_quit(con, 1); break; default: ship_key_quit_cancel(con); break; } } @ In the future, this function should handle more than two players per connection. Right? @d GET_SHIP(con, id) con->ship_hash[id] @= void player_input_multiple ( MatConnection *con, int key ) { ASSERT(con); ASSERT(con->ship_count == 2); ASSERT(con->ship_hash[0]); ASSERT(con->ship_hash[0]->type == MAT_MOVING_OBJ_SHIP); ASSERT(con->ship_hash[0]->info.player.conn_id == 0); ASSERT(con->ship_hash[0]->refs >= 0); ASSERT(con->ship_hash[1]); ASSERT(con->ship_hash[1]->type == MAT_MOVING_OBJ_SHIP); ASSERT(con->ship_hash[1]->info.player.conn_id == 1); ASSERT(con->ship_hash[1]->refs >= 0); ASSERT(con->ship_hash[0]->un == con->ship_hash[1]->un); switch (key) { case KEY_ARROW_UP: ship_key_up(con->ship_hash[0]); break; case KEY_ARROW_DOWN: ship_key_down(con->ship_hash[0]); break; case KEY_ARROW_RIGHT: ship_key_right(con->ship_hash[0]); break; case KEY_ARROW_LEFT: ship_key_left(con->ship_hash[0]); break; case '1': mat_bullet_new_player(con->ship_hash[0], 0, 1); break; case '2': mat_bullet_new_player(con->ship_hash[0], 1, 1); break; case '3': mat_bullet_new_player(con->ship_hash[0], 2, 1); break; case 'k': ship_key_up(con->ship_hash[1]); break; case 'j': ship_key_down(con->ship_hash[1]); break; case 'l': ship_key_right(con->ship_hash[1]); break; case 'h': ship_key_left(con->ship_hash[1]); break; case ' ': mat_bullet_new_player(con->ship_hash[1], 0, 1); break; case 'n': mat_bullet_new_player(con->ship_hash[1], 1, 1); break; case 'm': mat_bullet_new_player(con->ship_hash[1], 2, 1); break; case 'z': ship_key_stats(con->ship_hash[1]); break; case '0': ship_key_stats(con->ship_hash[0]); break; case 'p': ship_key_pause(con->ship_hash[0]); break; case '-': ship_key_zoom_out(con->ship_hash[1]); break; case '=': ship_key_zoom_in(con->ship_hash[1]); break; case '/': ship_key_zoom_out(con->ship_hash[0]); break; case '*': ship_key_zoom_in(con->ship_hash[0]); break; } } @ The following function handles the initialization for a machine. @= void machine_input_initial ( MatConnection *m, int key ) { switch (key) { case MMP_CLIENT_INITIAL_ID: @; break; default: @; break; } } @ @= { ASSERT(m); m->key_handler = machine_input_string; m->info.m.string_maxlength = 256; m->info.m.string = NULL; m->info.m.string_len = 0; m->info.m.string_siz = 0; m->info.m.handler = machine_input_arg_id_name; } @ @= void machine_input_arg_id_name ( MatConnection *m ) { VERBOSE("[Machine:%s]\n", m->info.m.string); free(m->info.m.string); m->key_handler = machine_input_string; m->info.m.string_maxlength = 256; m->info.m.string = NULL; m->info.m.string_len = 0; m->info.m.string_siz = 0; m->info.m.handler = machine_input_arg_id_ver; } @ @= void machine_input_arg_id_ver ( MatConnection *m ) { VERBOSE("[Version:%s]\n", m->info.m.string); free(m->info.m.string); mat_printf(m, "%c%s%c%s%c", MMP_SERVER_INITIAL_CONNECTED, PACKAGE, 0, VERSION, 0); mat_out_flush(m); m->key_handler = machine_input_default; } @ @= void machine_input_default ( MatConnection *m, int key ) { switch (key) { case MMP_CLIENT_DEFAULT_JOIN: VERBOSE("Command: join\n"); @; break; case MMP_CLIENT_DEFAULT_SHIPADD: VERBOSE("Command: shipadd\n"); @; break; default: @; break; #if 0 case MMP_CLIENT_DEFAULT_UNIVERSES: ; break; #endif } } @ If the machine sends a message we can't understand, we shut down its connection. We are very exigent and only talk to those we can understand. @= { char buffer[sizeof("Client sent unknown command: ?") + 1]; VERBOSE("Unknown command from machine: %d (%c)\n", key, key); sprintf(buffer, "Client sent unknown command: %c", key); mat_connection_free(m, MMP_SERVER_CLOSE_MMPERROR, buffer); } @ Here we add a ship. The arguments are the universe where we should add it (number) and the name given to the ship (string). @= { ASSERT(m); m->key_handler = machine_input_number; m->info.m.number_byte = 2; m->info.m.number = 0; m->info.m.handler = machine_input_arg_ship_add_string; } @ TODO: Make sure they can only enter alnums on the ship's name! @= void machine_input_arg_ship_add_string ( MatConnection *m ) { ASSERT(m); m->key_handler = machine_input_string; m->info.m.string_maxlength = 8; m->info.m.string = NULL; m->info.m.string_len = 0; m->info.m.string_siz = 0; m->info.m.handler = machine_input_arg_ship_add; } @ This one is used to read a number from the network. I like it very much. it keeps on reading bytes and adding them until number_byte becomes 0. That makes it very easy to set the length (in bytes) of the number. Once done reading the number, it calls the handler. @= void machine_input_number ( MatConnection *m, int key ) { ASSERT(m->info.m.number_byte > 0); ASSERT(0 <= key); ASSERT(key < 255); m->info.m.number = m->info.m.number * 255 + key; if (-- m->info.m.number_byte == 0) m->info.m.handler(m); } @ And now one to read strings. We keep on reading bytes and adding them to the buffer until we come across a 0. We then call the handler. If we already have the maximum number of characters allowed, we ignore the rest. @= void machine_input_string ( MatConnection *m, int key ) { if (m->info.m.string_len == m->info.m.string_maxlength) return; if (m->info.m.string_len == m->info.m.string_siz) @@; m->info.m.string[m->info.m.string_len ++] = key; if (key == 0) m->info.m.handler(m); } @ @= { m->info.m.string_siz = m->info.m.string_siz ? m->info.m.string_siz * 2 : 256; m->info.m.string = realloc(m->info.m.string, m->info.m.string_siz + 1); if (!m->info.m.string) { /* TODO: Shutdown this connection rather than the whole program! */ fprintf(stderr, "%s: realloc: %s\n", program_name, strerror(errno)); exit(EXIT_FAILURE); } } @ @= void machine_input_arg_ship_add ( MatConnection *m ) { MatUniverse *un; ASSERT(m); m->key_handler = machine_input_default; MAT_UNIVERSES_FIND(un, m->info.m.number); if (!un) { MAT_PROTOCOL_ERROR_SHIPADD(m, MMP_SERVER_SHIPADDFAIL_UNEXISTANT, (char *) NULL); return; } VERBOSE("Adding ship to universe: %d\n", un->id); @; @; mat_printf(m, "%c", MMP_SERVER_DEFAULT_SHIPADD_CLIENT); mat_out_flush(m); } @ @= { MatSub *i; ASSERT(un); for (i = un->subs; i; i = i->u_next) if (i->m != m) mat_printf(i->m, "%c%c%c%s%c", MMP_SERVER_DEFAULT_SHIPADD_OTHER, 0, 0, m->info.m.string, 0); } @ TODO: We ought to make sure the name entered is valid (only contains alnum). @= { MatMovingObj *s; s = malloc(sizeof(MatMovingObj)); if (!s) { mat_connection_free(m, MMP_SERVER_CLOSE_SYSERROR, strerror(errno)); return; } s->type = MAT_MOVING_OBJ_SHIP; @; MAT_SHIP_VIEW_DEFAULT(s); s->refs = 1; s->img = mat_ship; s->draw = 1; s->un = un; un->players_real++; ADD_MOVING_OBJ(s, un); s->rm_next = NULL; s->prevtype = NULL; s->nexttype = un->players_head; if (un->players_head) un->players_head->prevtype = s; else un->players_tail = s; un->players_head = s; ASSERT(m->info.m.string_len <= MAT_USER_MAX); strcpy(s->info.player.name, m->info.m.string); s->info.player.times_dead = 0; s->info.player.game_over = 0; s->info.player.chat_buffer_len = 0; s->info.player.chat_buffer[0] = 0; MAT_CONNECTION_SHIP_ADD(m, s); MAT_SHIP_VIEW_CHECK(s->un); start_game(s); message_broadcast(un, "-=> %s (%s) joins the game", s->info.player.name, m->addr); } @ With this command, a machine can join an existing universe. @= { ASSERT(m); m->key_handler = machine_input_number; m->info.m.number_byte = 2; m->info.m.number = 0; m->info.m.handler = machine_input_arg_join; } @ This one adds a universe to a connection. TODO: Add a maximum-per-machine limit to the number of subscriptions so a single mean machine won't be able to eat all our bandwidth. @= void machine_input_arg_join ( MatConnection *m ) { MatUniverse *un; ASSERT(m); m->key_handler = machine_input_default; MAT_UNIVERSES_FIND(un, m->info.m.number) if (!un) { MAT_PROTOCOL_ERROR_JOIN(m, MMP_SERVER_JOINFAIL_UNEXISTANT); return; } VERBOSE("Machine attempts to join universe: [%d]\n", un->id); @; @; } @ Here we report an error that takes place when a client attempts to join to a universe. @d MAT_PROTOCOL_ERROR_JOIN(m, reason) { mat_printf(m, "%c%c", MMP_SERVER_DEFAULT_JOIN_FAIL, reason); mat_out_flush(m); } @ And while we are at it, lets make a macro to report errors when the client attempts to join a ship to a given universe. @d MAT_PROTOCOL_ERROR_SHIPADD(m, reason, string) { mat_printf(m, "%c%c", MMP_SERVER_DEFAULT_SHIPADD_FAIL, reason); if (reason == MMP_SERVER_SHIPADDFAIL_BADNAME) mat_printf(m, "%s%c", string, 0); mat_out_flush(m); } @ Here we add machine |m| to the universe specified in |m->info.m.number|. We already know that such universe exists. The id of the universe is stored in m.info.m.number. @= { if (!mat_sub_add(m, un)) { mat_connection_free(m, MMP_SERVER_CLOSE_SYSERROR, strerror(errno)); return; } } @ Once a machine subscribes to a universe, we must sent a reply message MMP_SERVER_DEFAULT_JOIN_OK. @= { MatMovingObj *pl; mat_printf(m, "%c", MMP_SERVER_DEFAULT_JOIN_OK); for (pl = un->players_head; pl; pl = pl->nexttype) mat_printf(m, "%s%c", pl->info.player.name, 0); mat_printf(m, "%c", 0); mat_out_flush(m); } @ In the future, it should be possible for a machine to obtain a list of all the universes. For the moment, we ignore his request. @= { } @ @= void player_input_default ( MatConnection *con, int key ) { ASSERT(con); ASSERT(con->state == MAT_STATE_PLAYING); ASSERT(con->ship_count == 1); ASSERT(con->ship_hash[0]); ASSERT(con->ship_hash[0]->type == MAT_MOVING_OBJ_SHIP); ASSERT(con->ship_hash[0]->info.player.conn_id == 0); ASSERT(con->ship_hash[0]->refs >= 0); switch (key) { case '[': ship_key_view_prev(con->ship_hash[0]); break; case ']': ship_key_view_next(con->ship_hash[0]); break; case '-': case '_': ship_key_zoom_out(con->ship_hash[0]); break; case '=': case '+': ship_key_zoom_in (con->ship_hash[0]); break; case 'q': ship_key_quit(con, 0); break; case 'Q': ship_key_quit(con, 1); break; case 'p': ship_key_pause(con->ship_hash[0]); break; case 'w': ship_key_who(con->ship_hash[0]); break; case 'i': ship_key_visibility(con->ship_hash[0]); break; case 'l': case KEY_ARROW_RIGHT: ship_key_right(con->ship_hash[0]); break; case KEY_ARROW_LEFT: case 'h': ship_key_left(con->ship_hash[0]); break; case 'k': case KEY_ARROW_UP: ship_key_up(con->ship_hash[0]); break; case 'j': case KEY_ARROW_DOWN: ship_key_down(con->ship_hash[0]); break; case ' ': mat_bullet_new_player(con->ship_hash[0], 0, 1); break; case 'b': mat_bullet_new_player(con->ship_hash[0], 0, -1); break; case 'n': mat_bullet_new_player(con->ship_hash[0], 1, 1); break; case 'm': mat_bullet_new_player(con->ship_hash[0], 2, 1); break; case 's': ship_key_swappos(con->ship_hash[0]); break; case 'c': ship_key_messages_less(con->ship_hash[0]); break; case 'z': ship_key_stats(con->ship_hash[0]); break; case 'C': ship_key_messages_clean(con->ship_hash[0]); break; case 'v': ship_key_messages_view(con->ship_hash[0]); break; case 13: ship_key_chat_start(con); break; default: VERBOSE("Ignored Input: [key:%d][state:player_input_default]\n", key); } } @ @= void ship_key_quit ( MatConnection *con, int force ) { if (!force) { MatMovingObj *sh; /* TODO: Get rid of this assert! */ ASSERT(con->ship_count > 0); con->key_handler = player_input_quit; for (sh = con->ship_list; sh; sh = sh->info.player.conn_list_next) sprintf(message_get(sh), "-=> Are you sure you want to quit?"); } else { MESSAGE_FROM(con, "quits the game."); mat_connection_free(con, MMP_SERVER_CLOSE_CLIENT, "User quit. Bye bye."); } } @ @= void ship_key_quit_cancel ( MatConnection *con ) { MatMovingObj *sh; static char *msg[] = { "-=> I knew it!", "-=> Good! Have fun! :)", "-=> Hahahah, I knew you couldn't quit!", "-=> Great!", "-=> Wonderful...", "-=> Ooooer, stay stay stay! :)", "-=> I knew you weren't such a chicken!", "-=> Phew, you scared me.", "-=> Good. Now kill them all, you bastard!" }; ASSERT(con->ship_count > 0); con->key_handler = player_input_default; for (sh = con->ship_list; sh; sh = sh->info.player.conn_list_next) sprintf(message_get(sh), "%s", msg[rand() % (sizeof(msg) / sizeof(char *))]); } @ @= void ship_key_chat_wipe ( MatMovingObj *ship ) { ship->info.player.chat_buffer_len = 0; ship->info.player.chat_buffer[0] = 0; } @ @= void ship_key_chat_backspace ( MatMovingObj *ship ) { if (ship->info.player.chat_buffer_len > 0) { ship->info.player.chat_buffer_len--; ship->info.player.chat_buffer[ship->info.player.chat_buffer_len] = 0; } } @ @= void ship_key_messages_clean ( MatMovingObj *ship ) { ship->info.player.messages_count = 0; } @ @= void ship_key_messages_view ( MatMovingObj *ship ) { ship->info.player.messages_enabled = !ship->info.player.messages_enabled; } @ @= void ship_key_chat_start ( MatConnection *con ) { if (arg_chat) con->key_handler = player_input_buffer; } @ @= void ship_key_chat_end ( MatConnection *con ) { MatShip *pl; ASSERT(con->ship_count == 1); con->key_handler = player_input_default; pl = &con->ship_hash[0]->info.player; pl->chat_buffer[pl->chat_buffer_len] = 0; if (pl->chat_buffer_len > 0) { message_broadcast(con->ship_hash[0]->un, "%s> %s", pl->name, pl->chat_buffer); pl->chat_buffer_len = 0; pl->chat_buffer[0] = 0; pl->messages_enabled = 1; } } @ @= void ship_key_messages_less ( MatMovingObj *ship ) { if (ship->info.player.messages_count > 0) { ship->info.player.messages_count -= 1; ship->info.player.messages_start += 1; ship->info.player.messages_start %= MAXMESSAGES; } } @ @= void ship_key_swappos ( MatMovingObj *ship ) { ship->info.player.messages_pos = !ship->info.player.messages_pos; } @ @= void ship_key_pause ( MatMovingObj *ship ) { char *msg; ship->un->pause = !ship->un->pause; msg = ship->un->pause ? "freezes time" : "makes time go on"; message_broadcast(ship->un, "-=> %s %s . . .", ship->info.player.name, msg); } @ This function tells a player what are the other players in the universe he's in. @= void ship_key_who ( MatMovingObj *ship ) { MatMovingObj *pl; char *msg; int i = MAXMESSAGELEN; ASSERT(ship->type == MAT_MOVING_OBJ_SHIP); ASSERT(MAT_USER_MAX < MAXMESSAGELEN); msg = message_get(ship); i = sizeof("-=> Players: ") - 1; sprintf(msg, "-=> Players: "); for (pl = ship->un->players_head; pl; pl = pl->nexttype) { char *name; ASSERT(pl->type == MAT_MOVING_OBJ_SHIP); ASSERT(pl->un == ship->un); name = pl->info.player.name; ASSERT(name); if (i + strlen(name) + 2 + 3 >= MAXMESSAGELEN) { msg[i] = 0; msg = message_get(ship); i = 4; sprintf(msg, " "); } sprintf(msg + i, "[%s:%02d]", name, LIVES(pl)); i += strlen(name) + 2 + 3; } } @ @d LIVES(ship) arg_lives - ((arg_teams_count && arg_teams_share) ? ship->info.player.team->times_dead : ship->info.player.times_dead) @d HEALTH(x) ((int)(100 * (double)(x)->info.player.health / (double)(x)->un->health)) @= void ship_key_stats ( MatMovingObj *ship ) { ship->info.player.messages_enabled = 1; sprintf(message_get(ship), "[lives:%02d][health:%02d%%][players:%02d]", LIVES(ship), ship->info.player.health > 0 ? HEALTH(ship) : 0, ship->un->players_real); } @ @d SHIP_KEY_VIEW_LABEL(x) { if (x->info.player.view == x) sprintf(message_get(x), "-=> Centering view around yourself."); else { char *name = x->info.player.view->info.player.name; sprintf(message_get(x), "-=> Centering view around player %s", name); } } @ @d MAT_SHIP_VIEW_RM(SHIP) { if (SHIP->info.player.view_prev) SHIP->info.player.view_prev->info.player.view_next = SHIP->info.player.view_next; else { ASSERT(SHIP->info.player.view->info.player.viewers == SHIP); SHIP->info.player.view->info.player.viewers = SHIP->info.player.view_next; } if (SHIP->info.player.view_next) SHIP->info.player.view_next->info.player.view_prev = SHIP->info.player.view_prev; } @ @= { if (ship->info.player.view->info.player.viewers) ship->info.player.view->info.player.viewers->info.player.view_prev = ship; ship->info.player.view_prev = NULL; ship->info.player.view_next = ship->info.player.view->info.player.viewers; ship->info.player.view->info.player.viewers = ship; } @ @= #if MATANZA_ASSERT #define MAT_SHIP_VIEW_CHECK(X) mat_ship_view_check(X) #else #define MAT_SHIP_VIEW_CHECK(X) #endif @ @= #if MATANZA_ASSERT void mat_ship_view_check ( MatUniverse *un ); #endif @ @= #if MATANZA_ASSERT void mat_ship_view_check ( MatUniverse *un ) { MatMovingObj *ship; int count_total = 0, count_view = 0; for (ship = un->players_head; ship; ship = ship->nexttype) { MatMovingObj *i; count_total ++; for (i = ship->info.player.viewers; i; i = i->info.player.view_next) { count_view ++; ASSERT(i->info.player.view == ship); if (i->info.player.view_next) ASSERT(i->info.player.view_next->info.player.view_prev == i); if (!i->info.player.view_prev) ASSERT(i == ship->info.player.viewers); } } ASSERT(count_total == count_view); } #endif @ @= { if (ship->un->players_real == 1) { sprintf(message_get(ship), "-=> You are the only player in this universe!\n"); return; } } @ @= void ship_key_view_prev ( MatMovingObj *ship ) { ASSERT(ship); ASSERT(ship->refs > 0); ASSERT(ship->info.player.view); ASSERT(ship->info.player.view->refs > 0); MAT_SHIP_VIEW_CHECK(ship->un); @; MAT_SHIP_VIEW_RM(ship); ASSERT(ship->un->players_tail); ship->info.player.view = ship->info.player.view->prevtype; if (!ship->info.player.view) ship->info.player.view = ship->un->players_tail; ASSERT(ship->info.player.view); @; /* Print a message informing about the change of view. */ SHIP_KEY_VIEW_LABEL(ship); MAT_SHIP_VIEW_CHECK(ship->un); } @ @= void ship_key_view_next ( MatMovingObj *ship ) { ASSERT(ship); ASSERT(ship->refs > 0); ASSERT(ship->info.player.view); ASSERT(ship->info.player.view->refs > 0); MAT_SHIP_VIEW_CHECK(ship->un); @; MAT_SHIP_VIEW_RM(ship); ASSERT(ship->un->players_head); ship->info.player.view = ship->info.player.view->nexttype; if (!ship->info.player.view) ship->info.player.view = ship->un->players_head; ASSERT(ship->info.player.view); @; /* Print a message informing about the change of view. */ SHIP_KEY_VIEW_LABEL(ship); MAT_SHIP_VIEW_CHECK(ship->un); } @ @d CORRECTION 1.5 @= void ship_key_zoom_out ( MatMovingObj *ship ) { double nw, nh; nw = (double) ship->info.player.world_wi * 1.1; nh = GET_WORLD_HE(ship->info.player, nw); if ((int) nw < ship->un->mapsize_x && (int) nh < ship->un->mapsize_y) { ship->info.player.world_wi = (int) nw; ship->info.player.world_he = (int) nh; } } @ @= void ship_key_zoom_in ( MatMovingObj *ship ) { double nw, nh; nw = (double) ship->info.player.world_wi / 1.1; nh = GET_WORLD_HE(ship->info.player, nw); if ((int) nw > mat_ship[0].w - 2 && (int) nh > mat_ship[0].h - 2) { ship->info.player.world_wi = (int) nw; ship->info.player.world_he = (int) nh; } } @ @= void ship_key_chat_start ( MatConnection * ); void ship_key_chat_end ( MatConnection * ); void ship_key_view_next ( MatMovingObj *ship ); void ship_key_view_prev ( MatMovingObj *ship ); void ship_key_zoom_out ( MatMovingObj *ship ); void ship_key_zoom_in ( MatMovingObj *ship ); void ship_key_stats ( MatMovingObj *ship ); void ship_key_messages_clean ( MatMovingObj *ship ); void ship_key_messages_view ( MatMovingObj *ship ); void ship_key_chat_backspace ( MatMovingObj *ship ); void ship_key_chat_wipe ( MatMovingObj *ship ); void ship_key_pause ( MatMovingObj *ship ); void ship_key_who ( MatMovingObj *ship ); void ship_key_messages_less ( MatMovingObj *ship ); void ship_key_swappos ( MatMovingObj *ship ); void ship_key_up ( MatMovingObj *ship ); void ship_key_down ( MatMovingObj *ship ); void ship_key_left ( MatMovingObj *ship ); void ship_key_right ( MatMovingObj *ship ); void ship_key_visibility ( MatMovingObj *ship ); void ship_key_quit ( MatConnection *con, int force ); void ship_key_quit_cancel ( MatConnection *con ); void ship_key_chat_add ( MatMovingObj *ship, int key ); @ @= void ship_key_chat_add ( MatMovingObj *ship, int key ) { MatShip *p = &ship->info.player; if (isprint(key) && p->chat_buffer_len < MAXCHATBUFFERLEN) { p->chat_buffer[p->chat_buffer_len++] = (char)key; p->chat_buffer[p->chat_buffer_len] = 0; } else VERBOSE("Ignored Input: [key:%d][state:player_input_buffer]\n", key); } @ @= void ship_key_up ( MatMovingObj *ship ) { if (ship->info.player.game_over) { double mod_y, mod_t; if (ship->sp_y <= 0) mod_y = ship->sp_y - 1.0 / STEPS_MOVEMENT; else mod_y = 0; mod_t = sqrt(ship->sp_x * ship->sp_x + mod_y * mod_y); if (arg_speed_max == 0 || (-arg_speed_max < mod_t && mod_t < arg_speed_max)) { ship->sp = mod_t; ship->sp_y = mod_y; } } else if (ship->info.player.ship_speed_inc == 0) { ship->info.player.ship_speed_inc = 3; if (arg_space) { double mod_x, mod_y, mod_t; mod_x = ship->sp_x - 1.0 * mat_sin[(int)ship->ang] / STEPS_MOVEMENT; mod_y = ship->sp_y - 1.0 * mat_cos[(int)ship->ang] / STEPS_MOVEMENT; mod_t = sqrt(mod_x * mod_x + mod_y * mod_y); if (arg_speed_max == 0 || (-arg_speed_max < mod_t && mod_t < arg_speed_max)) { ship->sp = mod_t; ship->sp_x = mod_x; ship->sp_y = mod_y; } } else if (arg_speed_max == 0 || ship->sp + 1.0 / STEPS_MOVEMENT < (double)arg_speed_max) { ship->sp -= 1.0 / STEPS_MOVEMENT; ship->sp_x = ship->sp * mat_sin[(int)ship->ang]; ship->sp_y = ship->sp * mat_cos[(int)ship->ang]; } } } @ @= void ship_key_down ( MatMovingObj *ship ) { if (ship->info.player.game_over) { double mod_y, mod_t; if (ship->sp_y >= 0) mod_y = ship->sp_y + 1.0 / STEPS_MOVEMENT; else mod_y = 0; mod_t = sqrt(ship->sp_x * ship->sp_x + mod_y * mod_y); if (arg_speed_max == 0 || (-arg_speed_max < mod_t && mod_t < arg_speed_max)) { ship->sp = mod_t; ship->sp_y = mod_y; } } else if (ship->info.player.ship_speed_inc == 0 && arg_brake) { ship->info.player.ship_speed_inc = 3; if (arg_space) { double mod_x, mod_y, mod_t; mod_x = ship->sp_x + 1.0 * mat_sin[(int)ship->ang] / STEPS_MOVEMENT; mod_y = ship->sp_y + 1.0 * mat_cos[(int)ship->ang] / STEPS_MOVEMENT; mod_t = sqrt(mod_x * mod_x + mod_y * mod_y); if (arg_speed_max == 0 || (-arg_speed_max < mod_t && mod_t < arg_speed_max)) { ship->sp = mod_t; ship->sp_x = mod_x; ship->sp_y = mod_y; } } else if (arg_speed_max == 0 || -arg_speed_max < ship->sp - 1.0 / STEPS_MOVEMENT) { ship->sp += 1.0 / STEPS_MOVEMENT; if (!arg_fly_back && 0.0 < ship->sp) ship->sp = 0; ship->sp_x = ship->sp * mat_sin[(int)ship->ang]; ship->sp_y = ship->sp * mat_cos[(int)ship->ang]; } } } @ @= void ship_key_right ( MatMovingObj *ship ) { if (ship->info.player.game_over) { double mod_x, mod_t; if (ship->sp_x >= 0) mod_x = ship->sp_x + 1.0 / STEPS_MOVEMENT; else mod_x = 0; mod_t = sqrt(mod_x * mod_x + ship->sp_y * ship->sp_y); if (arg_speed_max == 0 || (-arg_speed_max < mod_t && mod_t < arg_speed_max)) { ship->sp = mod_t; ship->sp_x = mod_x; } } else if (arg_ang_speed_max > 0) { if (ship->sp_ang > 0) ship->sp_ang = 0; else if (ship->sp_ang > -arg_ang_speed_max) ship->sp_ang -= 1.0 / STEPS_MOVEMENT; } else { ship->ang -= 1; if ((int)ship->ang < 0) ship->ang += arg_ang; if (!arg_space) { ship->sp_x = ship->sp * mat_sin[(int)ship->ang]; ship->sp_y = ship->sp * mat_cos[(int)ship->ang]; } } } @ @= void ship_key_left ( MatMovingObj *ship ) { if (ship->info.player.game_over) { double mod_x, mod_t; if (ship->sp_x <= 0) mod_x = ship->sp_x - 1.0 / STEPS_MOVEMENT; else mod_x = 0; mod_t = sqrt(mod_x * mod_x + ship->sp_y * ship->sp_y); if (arg_speed_max == 0 || (-arg_speed_max < mod_t && mod_t < arg_speed_max)) { ship->sp = mod_t; ship->sp_x = mod_x; } } else if (arg_ang_speed_max > 0) { if (ship->sp_ang < 0) ship->sp_ang = 0; else if (ship->sp_ang < arg_ang_speed_max) ship->sp_ang += 1.0 / STEPS_MOVEMENT; } else { ship->ang += 1; if ((int)ship->ang > arg_ang - 1) ship->ang -= arg_ang; if (!arg_space) { ship->sp_x = ship->sp * mat_sin[(int)ship->ang]; ship->sp_y = ship->sp * mat_cos[(int)ship->ang]; } } } @ @d VISIBILITY_BROADCAST(obj) { MatMovingObj *i; char *msg; ASSERT(obj->type == MAT_MOVING_OBJ_SHIP); msg = obj->info.player.visible ? "-=> %s appears in the middle of nowhere !" : "-=> %s becomes invisible !"; for (i = obj->un->players_head; i; i = i->nexttype) { ASSERT(i->un == obj->un); if (i != obj && OBJECT_INSIDE(i, obj)) sprintf(message_get(i), msg, obj->info.player.name); } } @= void ship_key_visibility ( MatMovingObj *ship ) { if (ship->info.player.visible_exp > 0) { ship->info.player.visible = !ship->info.player.visible; VISIBILITY_BROADCAST(ship); } } @ We keep a list of maximum |MAXMESSAGES| messages. The messages expire when they are too old. @d NM ((p->info.player.messages_start + p->info.player.messages_count - 1) % MAXMESSAGES) @= char * message_get (MatMovingObj *p) { static char buffer[MAXMESSAGELEN]; if (p->type != MAT_MOVING_OBJ_SHIP || !p->info.player.conn || p->info.player.conn->state != MAT_STATE_PLAYING) return buffer; ASSERT(p); ASSERT(p->type == MAT_MOVING_OBJ_SHIP); ASSERT(p->info.player.conn); ASSERT(p->info.player.conn->state == MAT_STATE_PLAYING); if (p->info.player.messages_count == MAXMESSAGES) p->info.player.messages_start = (p->info.player.messages_start + 1) % MAXMESSAGES; else p->info.player.messages_count ++; p->info.player.messages_expire[NM] = 200; return p->info.player.messages[NM]; } void message_broadcast (MatUniverse *u, char *fmt, ...) { MatMovingObj *p; va_list arg; ASSERT(u); ASSERT(fmt); for (p = u->players_head; p; p = p->nexttype) { va_start(arg, fmt); vsprintf(message_get(p), fmt, arg); va_end(arg); } } @ @= int mat_bullet_new_player ( MatMovingObj *p, int type, int dir ); @ This function makes a new bullet. |p| is the player shooting the bullet. |sp| is the speed of the bullet. |dm| is the damage the bullet will do when it hits other players. |xp| is the number of times events should be processed before the bullet is removed. |pxp| is the number of ticks before the player will be allowed to shot again. @= int mat_bullet_new_player ( MatMovingObj *p, int type, int dir ) { double sp_x, sp_y; ASSERT(dir == 1 || dir == -1); ASSERT(p->type == MAT_MOVING_OBJ_SHIP); ASSERT(p->refs >= 0); @; sp_x = - dir * mat_bullets_speed[type] * mat_sin[(int)p->ang] + p->sp_x; sp_y = - dir * mat_bullets_speed[type] * mat_cos[(int)p->ang] + p->sp_y; return mat_bullet_new(p, type, sp_x, sp_y, p->ang); } @ @= int mat_bullet_new ( MatMovingObj *p, int type, double sp_x, double sp_y, double ang ); @ @= int mat_bullet_new ( MatMovingObj *p, int type, double sp_x, double sp_y, double ang ) { MatMovingObj *n; n = malloc(sizeof(MatMovingObj)); if (!n) { fprintf(stderr, "%s: %s\n", program_name, strerror(errno)); return 0; } MAT_MOVING_OBJ_REF(p); n->un = p->un; p->info.player.ship_bullets[type] --; if (p->info.player.ship_bullets[type] == 0) sprintf(message_get(p), "-=> Ooops, you ran out of %s !", mat_bullets_name[type]); if (type == 2) p->pal = mat_ship_palette[p->info.player.ship_bullets[2]]; p->info.player.bullets_expire += mat_bullets_pexp[type]; n->info.bullet.src = p; n->info.bullet.type = type; n->info.bullet.expires = mat_bullets_bexp[type]; n->type = MAT_MOVING_OBJ_BULLET; n->rm_next = NULL; n->ang = ang; n->sp_ang = 0; n->crash = 1; n->draw = 1; n->alpha = 1.0; n->alpha_mod = NULL; n->img = type > 0 ? mat_missile[type - 1] : NULL; n->sp_x = sp_x; n->sp_y = sp_y; ASSERT(p->img); n->pos_x = p->pos_x + (p->img[0].w - (type > 0 ? n->img[0].w : 0)) / 2; n->pos_y = p->pos_y + (p->img[0].h - (type > 0 ? n->img[0].h : 0)) / 2; if ((int)n->pos_x >= n->un->mapsize_x) n->pos_x -= n->un->mapsize_x; if ((int)n->pos_y >= n->un->mapsize_y) n->pos_y -= n->un->mapsize_y; ASSERT((int)n->pos_x >= 0); ASSERT((int)n->pos_y >= 0); ASSERT((int)n->pos_x < n->un->mapsize_x); ASSERT((int)n->pos_y < n->un->mapsize_y); n->pal = mat_ship_palette[0]; @; return 1; } @ @= { MatUniverse *un; un = n->un; n->prevtype = NULL; n->nexttype = un->bullets; if (un->bullets) un->bullets->prevtype = n; un->bullets = n; ADD_MOVING_OBJ(n, un); } @ @d DEL_MOVING_OBJ(obj) { if ((obj)->next) (obj)->next->prev = (obj)->prev; if ((obj)->prev) (obj)->prev->next = (obj)->next; else (obj)->un->objs = (obj)->un->objs->next; } @d ADD_MOVING_OBJ(obj, un) { (obj)->prev = NULL; (obj)->next = un->objs; if (un->objs) un->objs->prev = (obj); un->objs = (obj); } @ @= { if (p->info.player.bullets_expire > mat_bullets_pexp[type] / 2 || p->info.player.ship_bullets[type] <= 0 || p->info.player.game_over) return 0; } @ This should be optimized. We should get rid of universe_bitmask and keep this subscriptions as a list. This will break with the IDs for the universes when more than one universe gets supported. @= void machine_update ( MatConnection *self ) { int i; MatSub *un; for (i = 0; i < MAT_SUB_MACHINE_HASH_SIZE; i ++) for (un = self->info.m.subs[i]; un; un = un->m_next) { mat_printf(self, "%c%c%c", MMP_SERVER_DEFAULT_FRAME_SHIPS, un->u->id & 0xff00, un->u->id, 0x00ff); @; mat_printf(self, "%c", MMP_SERVER_FRAME_DONE); } mat_out_flush(self); } @ In this macro we send information about all the ships in the @d SEND_NUMBER(x) mat_printf(self, "%c%c", ((int)x) & 0xff00, ((int)x) & 0x00ff) @d SEND_STRING(x) mat_printf(self, "%s%c", ((char *)x), 0); @= { MatMovingObj *sh; for (sh = un->u->players_head; sh; sh = sh->nexttype) mat_printf(self, "%c%c" "%c%c" "%c%c", ((int) sh->pos_x) & 0xff00, ((int) sh->pos_x) & 0x00ff, ((int) sh->pos_y) & 0xff00, ((int) sh->pos_y) & 0x00ff, ((int) sh->ang ) & 0xff00, ((int) sh->ang ) & 0x00ff); } @ @= void draw_world ( MatConnection *self ) { int game_moving; ASSERT(self); ASSERT(self->state == MAT_STATE_PLAYING); @; if (game_moving) @@; MAT_GRAPH_RENDER_NOWIPE_ALL(self); @; MAT_FLUSH_ALL(self); } @ @= { MatMovingObj *sh = self->ship_list; game_moving = 0; do { if (!sh->un->pause) { game_moving = 1; break; } else sh = sh->info.player.conn_list_next; } while (sh); } @ @= { MatMovingObj *i; MatMovingObj *sh; MatShip *pl; MatShip *pl_view; MatUniverse *un; for (i = self->ship_list; i; i = i->info.player.conn_list_next) { ASSERT(i->type == MAT_MOVING_OBJ_SHIP); pl = &i->info.player; sh = i->info.player.view; ASSERT(sh); ASSERT(sh->type == MAT_MOVING_OBJ_SHIP); un = sh->un; ASSERT(un); pl_view = &sh->info.player; if (arg_radar && un->updates % 4) { MatMovingObj *obj; for (obj = un->ast; obj; obj = obj->nexttype) if (!OBJECT_INSIDE(sh, obj)) @; for (obj = un->players_head; obj; obj = obj->nexttype) if (!OBJECT_INSIDE(sh, obj) && !obj->info.player.game_over) @; } @; } } @ Here we draw everything that gets rendered. @= { int startx; int starty; MatMovingObj *sh; MatMovingObj *i; MatMovingObj *p; MatMovingObj *obj; MatShip *pl; MatShip *pl_view; MatUniverse *un; TERM_CLEAR_IMAGE(self); for (i = self->ship_list; i; i = i->info.player.conn_list_next) { ASSERT(i->type == MAT_MOVING_OBJ_SHIP); pl = &i->info.player; sh = i->info.player.view; ASSERT(sh); ASSERT(sh->type == MAT_MOVING_OBJ_SHIP); pl_view = &sh->info.player; un = sh->un; ASSERT(un); ASSERT((int)sh->pos_x >= 0); ASSERT((int)sh->pos_x < un->mapsize_x); ASSERT((int)sh->pos_y >= 0); ASSERT((int)sh->pos_y < un->mapsize_y); ASSERT(pl->world_wi > 0); ASSERT(pl->world_he > 0); startx = sh->pos_x - (pl->world_wi - sh->img[0].w) / 2; starty = sh->pos_y - (pl->world_he - sh->img[0].h) / 2; if (startx < 0) startx += un->mapsize_x; if (starty < 0) starty += un->mapsize_y; ASSERT(startx >= 0); ASSERT(starty >= 0); ASSERT(startx < un->mapsize_x); ASSERT(starty < un->mapsize_y); @; for (obj = un->ast; obj; obj = obj->nexttype) @; for (obj = un->smart_objs; obj; obj = obj->nexttype) @; for (p = un->players_head; p; p = p->nexttype) if (/*OBJECT_INSIDE(sh, p) &&*/ p->info.player.visible && p->draw) @; for (obj = un->bullets; obj; obj = obj->nexttype) @; if (pl_view->game_over && pl->messages_enabled) @; } } @ TODO: Get this to work with ppc != 1 @= { int imgwi, imghe; imgwi = pl->win_x_e - pl->win_x_s; imghe = pl->win_y_e - pl->win_y_s; print(self, pl->win_x_s * 2 + imgwi - 2 * 2 * imgwi / 5, pl->win_y_s * 2 + imghe / 2, 2 * imgwi / 5, 2 * imghe / 4, &font, 255, "Game"); print(self, pl->win_x_s * 2 + imgwi - 2 * 2 * (imgwi / 5), pl->win_y_s * 2 + imghe, 2 * imgwi / 5, 2 * imghe / 4, &font, 255, "Over"); } @ @d POSB() (pl->messages_pos ? pl->win_y_s + 1 : pl->win_y_e - 2) @d NMESG(x) ((pl->messages_start + x) % MAXMESSAGES) @= { int i, pos; ASSERT(pl); pos = pl->messages_pos ? pl->win_y_e - pl->messages_count - 1 : pl->win_y_s + 1; for (i = 0; i < pl->messages_count; i ++) { if (pl->messages_enabled) mat_print(self, 1, pos + i, MAT_NORMAL, pl->messages[NMESG(i)], 0); if (pl->messages_expire[NMESG(i)] -- == 0) { pl->messages_start = NMESG(1); pl->messages_count --; } } if (self->ship_count == 1 && self->key_handler == player_input_buffer) { mat_print(self, 1, POSB(), MAT_NORMAL, "> ", 0); mat_print(self, 3, POSB(), MAT_NORMAL, pl->chat_buffer, 0); } } @ @= { MatImgWorld *obj; for (obj = mat_bg_head; obj; obj = obj->next) { @; } if (un->bg) { ASSERT(un->bg->w <= un->mapsize_x); ASSERT(un->bg->h <= un->mapsize_y); MAT_IMAGE_DRAW_ST(self, i, un->bg, startx, starty, mat_stdpal, arg_bg_adj, 1.0); } if (un->dots) { int i, j; ASSERT(self); ASSERT(self->graph_imagebuffer); for (i = 20 - starty % 20; i < pl->imghe; i += 20) for (j = 40 - startx % 40; j < pl->imgwi; j += 40) MAT_GRAPH_DRAW(self, pl, j, i, 100); } } @ If the player |self| can see the object |obj|, we draw it. @= { int x, y; ASSERT(obj); ASSERT(!obj->rm_next); ASSERT(self); ASSERT((int) obj->pos_x >= 0); ASSERT((int) obj->pos_y >= 0); ASSERT((int) obj->pos_x < un->mapsize_x); ASSERT((int) obj->pos_y < un->mapsize_y); if (obj->draw) { if (obj->img == NULL) { x = (int) obj->pos_x - startx; y = (int) obj->pos_y - starty; if (x < 0) x += un->mapsize_x; if (y < 0) y += un->mapsize_y; ASSERT(x < un->mapsize_x); ASSERT(y < un->mapsize_y); ASSERT(x >= 0); ASSERT(y >= 0); if (x < pl->world_wi && y < pl->world_he) { @; ASSERT(x >= 0); ASSERT(x < self->graph_imgwidth); ASSERT(y >= 0); ASSERT(y < self->graph_imgheight); MAT_GRAPH_DRAW(self, pl, x, y, 255); } } else { MatImage *img; int x, y; img = &obj->img[(int) obj->ang]; x = (int) obj->pos_x; y = (int) obj->pos_y; MAT_IMAGE_DRAW_DY(self, i, img, x, y, obj, startx, starty, 0); } } } @ @= unsigned char mat_stdpal[256] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255 }; @ This macro is used to adjust the colors in a given image so the minimum color will be projected to col_min and the maximum to col_max. @= { unsigned char col_r_min, col_r_max; int bufsize = img->h * img->w; @; if (col_r_min != col_min || col_r_max != col_max) @; } @ @= { double rate; int i; ASSERT(bufsize == img->h * img->w); if (col_r_max == col_r_min) rate = 0; else rate = ((double)col_max - (double)col_min) / ((double)col_r_max - (double)col_r_min); for (i = 0; i < bufsize; i ++) { img->img[i] = col_min + (img->img[i] - col_r_min) * rate; ASSERT(col_min <= img->img[i]); ASSERT(img->img[i] <= col_max); } } @ @= { int i; col_r_min = col_r_max = img->img[0]; for (i = 1; i < bufsize; i ++) { unsigned char tmp = img->img[i]; if (tmp < col_r_min) col_r_min = tmp; else if (col_r_max < tmp) col_r_max = tmp; } } @ Here we prepare the palettes used to draw stuff. @= { int i; for (i = 0; i < 3; i ++) { mat_ship_palette[i] = malloc(sizeof(int) * 256); if (!mat_ship_palette[i]) { fprintf(stderr, "%s: %s\n", program_name, strerror(errno)); exit(EXIT_FAILURE); } mat_ship_palette[i]['*'] = 100; mat_ship_palette[i]['X'] = 255; mat_ship_palette[i]['.'] = 0; mat_ship_palette[i][' '] = 0; } mat_ship_palette[2]['1'] = 255; mat_ship_palette[2]['2'] = 255; mat_ship_palette[2]['3'] = 255; mat_ship_palette[2]['4'] = 255; mat_ship_palette[1]['1'] = 0; mat_ship_palette[1]['2'] = 255; mat_ship_palette[1]['3'] = 100; mat_ship_palette[1]['4'] = 255; mat_ship_palette[0]['1'] = 0; mat_ship_palette[0]['2'] = 0; mat_ship_palette[0]['3'] = 100; mat_ship_palette[0]['4'] = 100; } @ @= { free(mat_ship_palette[0]); free(mat_ship_palette[1]); free(mat_ship_palette[2]); free(mat_ship_palette[3]); } @ @= { if (pl->imgwi != pl->world_wi) x = (double) x * (double) pl->imgwi / (double) pl->world_wi; if (pl->imghe != pl->world_he) y = (double) y * (double) pl->imghe / (double) pl->world_he; } @ We use MAT_SHIPSIZE_. / . because the ships don't take the whole MAT_SHIPSIZE_. yet. In the future, as the matrixes for the ships get optimized, this should be changed to MAT_SHIPSIZE_. / 2. @d ABS(x) ((x) >= 0 ? (x) : -(x)) @d MAXWI(p) p->info.player.world_wi / 2 + p->img[0].w / 2 @d MAXHE(p) p->info.player.world_he / 2 + p->img[0].h / 2 @d OBJECT_INSIDE(p, q) ( p == q || ( ( ABS(q->pos_x - p->pos_x) < MAXWI(p) || p->un->mapsize_x - ABS(q->pos_x - p->pos_x) < MAXWI(p) ) && ( ABS(q->pos_y - p->pos_y) < MAXHE(p) || p->un->mapsize_y - ABS(q->pos_y - p->pos_y) < MAXHE(p) ) ) ) @ Here we draw the first letter of the name of player |obj| in the direction self should move to reach him. @= { double x, y, m; int wi, he, dx, dy, draw = 1; char buffer[2]; ASSERT(obj != sh); @; m = y / x; ASSERT(x >= 0); ASSERT(y >= 0); ASSERT(pl->imgwi > 0); ASSERT(pl->imghe > 0); if (m <= (double) pl->imghe / (double) pl->imgwi) { wi = dx > 0 ? pl->imgwi - 1: 0; he = (pl->imghe + dy * m * pl->imgwi) / 2; } else { he = dy > 0 ? pl->imghe - 1: 0; wi = (pl->imgwi + dx * pl->imghe / m) / 2; } ASSERT(0 <= he); ASSERT(he < pl->imghe); ASSERT(0 <= wi); ASSERT(wi < pl->imgwi); ASSERT(he == 0 || he == pl->imghe - 1 || wi == 0 || wi == pl->imgwi - 1); @; if (draw) mat_print(self, wi / 2 + pl->win_x_s, he / 2 + pl->win_y_s, MAT_NORMAL, buffer, 0); } @ @d ADJUST_POSITION(res, pos, w, map) { ASSERT((int)pos >= 0); ASSERT((int)pos < map); ASSERT(w < map); ASSERT(w >= 0); res = pos + w / 2; if (res >= map) res -= map; ASSERT(res >= 0); ASSERT(res < map); } @= { double px, sx, py, sy; double x1, x2, y1, y2; ASSERT(obj); ASSERT(sh); ASSERT(obj->un == sh->un); ASSERT(!obj->rm_next); ASSERT(!sh->rm_next); ASSERT(obj->img); ASSERT(sh->img); ADJUST_POSITION(px, obj->pos_x, obj->img->w, obj->un->mapsize_x); ADJUST_POSITION(sx, sh->pos_x, sh->img->w, obj->un->mapsize_x); x1 = ABS(px - sx); x2 = obj->un->mapsize_x - x1; if (x1 < x2) x = x1, dx = 1; else x = x2, dx = -1; dx = sx <= px ? dx : -dx; ADJUST_POSITION(py, obj->pos_y, obj->img->h, obj->un->mapsize_y); ADJUST_POSITION(sy, sh->pos_y, sh->img->h, obj->un->mapsize_y); y1 = ABS(py - sy); y2 = obj->un->mapsize_y - y1; if (y1 < y2) y = y1, dy = 1; else y = y2, dy = -1; dy = sy <= py ? dy : -dy; } @ @d LENAWAY (pl->world_wi * pl->world_wi + pl->world_he * pl->world_he) @d LENNEAR (pl->world_wi * pl->world_wi + pl->world_he * pl->world_he) / 2 @= { int dist; ASSERT(obj); dist = x * x + y * y; if (dist > LENAWAY) { if (obj->type == MAT_MOVING_OBJ_SHIP) buffer[0] = tolower(obj->info.player.name[0]); else draw = 0; } else if (dist > LENNEAR) { if (obj->type == MAT_MOVING_OBJ_SHIP) buffer[0] = toupper(obj->info.player.name[0]); else buffer[0] = '.'; } else { if (obj->type == MAT_MOVING_OBJ_SHIP) buffer[0] = '*'; else buffer[0] = '+'; } buffer[1] = 0; } @ @= if (self->graph_imgwidth != self->world_wi) pos_x = pos_x * (double)self->graph_imgwidth / (double) self->world_wi; if (self->graph_imgheight != self->world_he) pos_y = pos_y * (double)self->graph_imgheight / (double) self->world_he; @ |ships.c| contains an array with the matrix for all the possible angles. @d MAT_GRAPH_CORD(p,s,x,y) ((int)(((x) + 2 * (s)->win_x_s) + ((y) + 2 * (s)->win_y_s) * (p)->graph_imgwidth)) @d MAT_GRAPH_DRAW(p,s,x,y,b) ((p)->graph_imagebuffer[MAT_GRAPH_CORD(p,s,x,y)] = (b)) @d MAT_GRAPH_DRAW_ALPHA(p,s,x,y,b,a) { unsigned char *xcol = &(p)->graph_imagebuffer[MAT_GRAPH_CORD(p, s, x, y)]; ASSERT(0.0 <= a); ASSERT(a <= 1.0); ASSERT(0 <= b); ASSERT(b <= 255); ASSERT(0 <= (int)((double)(b) * (a) + (double)*xcol * (1 - (a)))); ASSERT((int)((double)(b) * (a) + (double)*xcol * (1 - (a))) <= 255); *xcol = (char)((double)(b) * (a) + (double)*xcol * (1 - (a))); } @= { MatImage *img; int x, y; ASSERT(p); ASSERT(p->type == MAT_MOVING_OBJ_SHIP); ASSERT(p->info.player.ship_bullets[2] >= 0); ASSERT(p->info.player.ship_bullets[2] <= 2); ASSERT(!p->rm_next); x = (int) p->pos_x; y = (int) p->pos_y; ASSERT(0 <= x); ASSERT(x < i->un->mapsize_x); ASSERT(0 <= y); ASSERT(y < i->un->mapsize_y); img = &p->img[(int)p->ang]; ASSERT(img); MAT_IMAGE_DRAW_DY(self, i, img, x, y, p, startx, starty, 0); } @ @= void machine_update ( MatConnection *self ); void draw_world ( MatConnection *p ); void start_game ( MatMovingObj *p ); char *message_get ( MatMovingObj *p ); void message_broadcast ( MatUniverse *, char *, ...); @ @= void player_input_quit ( MatConnection *p, int key ); void player_input_default ( MatConnection *p, int key ); void player_input_buffer ( MatConnection *p, int key ); void player_input_multiple ( MatConnection *p, int key ); void machine_input_initial ( MatConnection *p, int key ); void machine_input_default ( MatConnection *p, int key ); void machine_input_string ( MatConnection *m, int key ); void machine_input_number ( MatConnection *m, int key ); void machine_input_arg_join ( MatConnection *m ); void machine_input_arg_ship_add ( MatConnection *m ); void machine_input_arg_ship_add_string ( MatConnection *m ); void machine_input_arg_id_name ( MatConnection *m ); void machine_input_arg_id_ver ( MatConnection *m ); @ For the moment, a random location. In the future we might pick up one from a list of locations or it might depend on the player's team or something. @= { ship->pos_x = (double)(rand() % ship->un->mapsize_x); ship->pos_y = (double)(rand() % ship->un->mapsize_y); ship->ang = (double)(rand() % arg_ang); ship->sp_ang = arg_ang_speed_max == 0 ? 0 : (double)(rand() % 5 - 2) / 10; ship->sp = 0; ship->sp_x = 0; ship->sp_y = 0; } @* Asteroids The struct containing asteroids: @= typedef struct MatAst MatAst; struct MatAst { int size; int health; }; @ @= int mat_ast_health[] = { 500, 300 }; @ Here we add a few asteroids at random positions in the game. In the future, we ought to make sure we are not adding asteroids in places where players can see them appear all of a sudden. @= { ASSERT(un); while (un->ast_cur < arg_ast_num) AST_ADD_RANDOMPOS(0, un); #if 0 arg_ast_num = mat_ast_cur; fprintf(stderr, "%s: Resetting number of asteroids to %d\n", program_name, arg_ast_num); #endif } @ We need a function that takes the asteroid size and adds a given asteroid. @= int ast_add ( int ); @ @d AST_ADD_RANDOMPOS(size, un) { ASSERT(un->mapsize_x > 0); ASSERT(un->mapsize_y > 0); AST_ADD_POS(size, rand() % un->mapsize_x, rand() % un->mapsize_y, ((double)((rand() % 10) - 5)) / STEPS_MOVEMENT, ((double)((rand() % 10) - 5)) / STEPS_MOVEMENT, un); ASSERT(un->ast_cur > 0); } @d AST_ADD_POS(size, x, y, sx, sy, un) { MatMovingObj *ast; AST_ADD(ast, size, un); ASSERT(x >= 0); ASSERT(x < un->mapsize_x); ASSERT(y >= 0); ASSERT(y < un->mapsize_y); ast->pos_x = x; ast->pos_y = y; ast->sp_x = sx; ast->sp_y = sy; } @d AST_ADD(ast_new, sz, unx) { ast_new = malloc(sizeof(MatMovingObj)); ast_new->type = MAT_MOVING_OBJ_AST; ast_new->rm_next = NULL; ASSERT(mat_ast[sz]); ast_new->img = mat_ast[sz]; ast_new->pal = mat_ship_palette[0]; ast_new->ang = (double)(rand() % arg_ang); ast_new->sp_ang = ((double)(rand() % arg_ang) - arg_ang / 2) / (20 * STEPS_MOVEMENT); ast_new->info.ast.size = sz; ast_new->info.ast.health = mat_ast_health[sz]; ast_new->crash = 1; ast_new->draw = 1; ast_new->alpha = 1.0; ast_new->alpha_mod = NULL; ast_new->un = unx; ast_new->nexttype = unx->ast; ast_new->prevtype = NULL; if (unx->ast) unx->ast->prevtype = ast_new; unx->ast = ast_new; ADD_MOVING_OBJ(ast_new, unx); unx->ast_cur ++; ASSERT(ast_new->img); } @ @= typedef struct MatImgWorld MatImgWorld; struct MatImgWorld { MatImage *img; //MatImage *trans; char *path; MatImgWorld *next; MatImgWorld *prev; //MatMovingObj *mv; }; @ @= MatImgWorld *mat_bg_head = NULL; MatImgWorld *mat_bg_tail = NULL; MatImgWorld *mat_fg_head = NULL; MatImgWorld *mat_fg_tail = NULL; @ TODO: Make sure the images are big enough. @= { MatImgWorld *tmp; for (tmp = mat_bg_head; tmp; tmp = tmp->next) { tmp->img = mat_png_load(tmp->path); if (arg_bg_color_max != -1) { int col_min = 0; int col_max = arg_bg_color_max; MatImage *img = tmp->img; @; } } for (tmp = mat_fg_head; tmp; tmp = tmp->next) tmp->img = mat_png_load(tmp->path); if (arg_bg_size && (mat_bg_head || mat_fg_tail)) arg_mapsize_x = arg_mapsize_y = 0; for (tmp = mat_bg_head; tmp; tmp = tmp->next) { arg_mapsize_x = MAX(arg_mapsize_x, tmp->img->w); arg_mapsize_y = MAX(arg_mapsize_y, tmp->img->h); } for (tmp = mat_fg_head; tmp; tmp = tmp->next) { arg_mapsize_x = MAX(arg_mapsize_x, tmp->img->w); arg_mapsize_y = MAX(arg_mapsize_y, tmp->img->h); } } @ @= { ASSERT(obj->img->w <= sh->un->mapsize_x); ASSERT(obj->img->h <= sh->un->mapsize_y); MAT_IMAGE_DRAW_ST(self, i, obj->img, startx, starty, mat_stdpal, arg_bg_adj, 1.0); } @ @= { MatImgWorld *tmp; tmp = malloc(sizeof(MatImgWorld)); if (!tmp) { fprintf(stderr, "%s: %s\n", program_name, strerror(errno)); exit(EXIT_FAILURE); } tmp->path = optarg; tmp->next = NULL; tmp->prev = mat_bg_tail; if (mat_bg_tail) mat_bg_tail->next = tmp; else mat_bg_head = tmp; mat_bg_tail = tmp; } @* Code for reading PNG images This is just glue that allows Matanza to read PNG images. It depends on libpng. @= #if HAVE_PNG_H #include #endif @ We have just one function, mat_png_load. It is given a pathname and returns a pointer to an image (|MatImage|). Should an error take place, it aborts (I think). @= MatImage *mat_png_load ( char const *path ); @ The PNG code goes here. It is only compiled in if they have the PNG library. @= #if HAVE_LIBPNG @@; #else @@; #endif @ @= MatImage * mat_png_load ( char const *path ) { fprintf(stderr, "%s: Support for loading PNG files not included\n", program_name); exit(EXIT_FAILURE); } @ @= MatImage * mat_png_load ( char const *path ) { png_structp png_ptr; png_infop info_ptr; FILE *fp; MatImage *nimg; int bd, color; fp = fopen(path, "rb"); if (!fp) { fprintf(stderr, "%s: %s: %s\n", program_name, path, strerror(errno)); exit(EXIT_FAILURE); } @; @; @; @; @; return nimg; } @ @= { if (color != PNG_COLOR_TYPE_GRAY && color != PNG_COLOR_TYPE_GRAY_ALPHA) { fprintf(stderr, "%s: Only grayscale PNG files are supported\n", program_name); exit(EXIT_FAILURE); } } @ @= { /* read rest of file, and get additional chunks in info_ptr - REQUIRED */ png_read_end(png_ptr, info_ptr); /* clean up after the read, and free any memory allocated - REQUIRED */ png_destroy_read_struct(&png_ptr, &info_ptr, NULL); } @ @= { int y, len, dst; png_bytep row_pointers; len = png_get_rowbytes(png_ptr, info_ptr); row_pointers = malloc(len); ASSERT(color == PNG_COLOR_TYPE_GRAY || color == PNG_COLOR_TYPE_GRAY_ALPHA); for (y = dst = 0; y < nimg->h; y++) { int rd, stop; png_read_rows(png_ptr, &row_pointers, NULL, 1); for (rd = 0, stop = dst + nimg->w; dst != stop; rd ++) { png_byte p; p = row_pointers[rd]; nimg->img[dst ++] = p; } } free(row_pointers); } @ @= { png_uint_32 w, h; int dummy; /* Create and initialize the png_struct with the desired error handler * functions. If you want to use the default stderr and longjump method, * you can supply NULL for the last three parameters. We also supply the * the compiler header file version, so that we know if the application * was compiled with a compatible version of the library. REQUIRED */ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) return 0; /* Allocate/initialize the memory for image information. REQUIRED. */ info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { fprintf(stderr, "%s: %s\n", program_name, strerror(errno)); png_destroy_read_struct(&png_ptr, NULL, NULL); exit(EXIT_FAILURE); } if (setjmp(png_ptr->jmpbuf)) { fprintf(stderr, "%s: %s\n", program_name, strerror(errno)); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); exit(EXIT_FAILURE); } png_init_io(png_ptr, fp); png_read_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, &w, &h, &bd, &color, &dummy, NULL, NULL); nimg = malloc(sizeof(MatImage)); if (!nimg) { fprintf(stderr, "%s: %s\n", program_name, strerror(errno)); exit(EXIT_FAILURE); } nimg->w = w; nimg->h = h; nimg->img = malloc(w * h); if (!nimg->img) { fprintf(stderr, "%s: %s\n", program_name, strerror(errno)); exit(EXIT_FAILURE); } } @ Set up the data transformations you want. @= { png_color_16 my_background, *image_background; /* Extract multiple pixels with bit depths of 1, 2, and 4 from a single * byte into separate bytes (useful for paletted and grayscale images). */ png_set_packing(png_ptr); /* Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */ if ((color == PNG_COLOR_TYPE_GRAY && bd < 8) || png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_expand(png_ptr); /* Set the background color to draw transparent and alpha images over. * It is possible to set the red, green, and blue components directly * for paletted images instead of supplying a palette index. Note that * even if the PNG file supplies a background, you are not required to * use it - you should use the (solid) application background if it has one. */ if (png_get_bKGD(png_ptr, info_ptr, &image_background)) png_set_background(png_ptr, image_background, PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); else png_set_background(png_ptr, &my_background, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); if (png_set_interlace_handling(png_ptr) != 1) { fprintf(stderr, "%s: %s: Interlaced PNGs are not supported\n", program_name, path); exit(EXIT_FAILURE); } /* Optional call to gamma correct and add the background to the palette * and update info structure. REQUIRED if you are expecting libpng to * update the palette for you (ie you selected such a transform above). */ png_read_update_info(png_ptr, info_ptr); } @* Universes In this section we will handle information about the universe. @ @= { char *tmp; tmp = xmlGetProp(doc->root, "name"); strncpy(un->name, tmp ? tmp : "Unnamed Universe", MAX_UNIVERSE_NAME); } @ @d SET_CRASH_DAMAGE(obj, name) { char *tmp; tmp = xmlGetProp(doc->root, name); un->crash_damage[obj] = tmp ? atoi(tmp) : 0; } @= { SET_CRASH_DAMAGE(MAT_MOVING_OBJ_SHIP, "shipcrash"); } @ @= { char *tmpx, *tmpy; tmpx = xmlGetProp(doc->root, "mapsizex"); un->mapsize_x = tmpx ? atoi(tmpx) : arg_mapsize_x; tmpy = xmlGetProp(doc->root, "mapsizey"); un->mapsize_y = tmpy ? atoi(tmpy) : arg_mapsize_y; } @ @= { char *tmp; tmp = xmlGetProp(doc->root, "dots"); if (!tmp) un->dots = arg_bg_dots; else if (!strcasecmp(tmp, "yes")) un->dots = 1; else if (!strcasecmp(tmp, "no")) un->dots = 0; else un->dots = arg_bg_dots; } @ @= { char *tmp; tmp = xmlGetProp(doc->root, "health"); un->health = tmp ? atoi(tmp) : arg_health; } @ @= { int i; ASSERT(un); un->players_head = un->players_tail = NULL; un->bullets = un->ast = un->objs = un->smart_objs = NULL; un->objs_rm = (void *) &main; un->players_real = un->ast_cur = 0; un->pause = 0; un->subs = NULL; un->updates = 0; for (i = 0; i < 256; i ++) un->location[i] = NULL; ASSERT(sizeof("Default Universe") + 1 < MAX_UNIVERSE_NAME); strcpy(un->name, "Default Universe"); un->mapsize_x = arg_mapsize_x; un->mapsize_y = arg_mapsize_y; un->dots = arg_bg_dots; un->health = arg_health; } @ @= { xmlDocPtr doc; xmlNodePtr node; ASSERT(un); ASSERT(un->path); doc = xmlParseFile(un->path); if (!doc || !doc->root || !doc->root->name || strcasecmp(doc->root->name, "Universe")) { fprintf(stderr, "%s: %s: Corrupted Universe\n", program_name, un->path); exit(EXIT_FAILURE); } @; @; @; @; @; un->bg.src = xmlGetProp(doc->root, "background"); un->mask.src = xmlGetProp(doc->root, "mask"); MAT_UNIVERSE_LOCATIONS_SETALL(un, NULL); for (node = doc->root->childs; node; node = node->next) { if (!strcasecmp(node->name, "Location")) { int color; @; if (un->location[color]) free(un->location[color]); un->location[color] = malloc(sizeof(MatLocation)); if (!un->location[color]) { fprintf(stderr, "%s: %s\n", program_name, strerror(errno)); exit(EXIT_FAILURE); } @; } else fprintf(stderr, "%s: %s: %s: Ignoring tag\n", program_name, un->path, node->name); } @; #if 0 #endif } @ @d LIBXML_MULTIPLE_BOOL(type, prop, name) { char *tmp; tmp = xmlGetProp(node, name); un->location[color]->prop[type] = tmp && !strcasecmp(tmp, "yes"); } @d LIBXML_MULTIPLE_FLOAT(type, prop, name, default) { char *tmp; tmp = xmlGetProp(node, name); un->location[color]->prop[type] = tmp ? atof(tmp) : default; } @= { char *tmp_health; LIBXML_MULTIPLE_BOOL(MAT_MOVING_OBJ_SHIP, crash, "shipcrash"); LIBXML_MULTIPLE_BOOL(MAT_MOVING_OBJ_BULLET, crash, "astcrash"); LIBXML_MULTIPLE_BOOL(MAT_MOVING_OBJ_AST, crash, "bulletcrash"); LIBXML_MULTIPLE_FLOAT(MAT_MOVING_OBJ_SHIP, move, "shipmove", 1.0); LIBXML_MULTIPLE_FLOAT(MAT_MOVING_OBJ_BULLET, move, "astmove", 1.0); LIBXML_MULTIPLE_FLOAT(MAT_MOVING_OBJ_AST, move, "bulletmove", 1.0); tmp_health = xmlGetProp(node, "health"); un->location[color]->health = tmp_health ? atoi(tmp_health) : 0; } @ @= { int i; for (i = 0; i < 256; i ++) if (un->location[i] == NULL) un->location[i] = &mat_location_default; } @ @d MAT_UNIVERSE_LOCATIONS_SETALL(un, val) { int i; for (i = 0; i < 256; i ++) un->location[i] = val; } @ @= { char *tmp; tmp = xmlGetProp(node, "color"); if (tmp) { color = atoi(tmp); if (color < 0) color = 0; else if (color > 255) color = 255; } else color = 0; } @ TODO: Give verbose descriptions of the problems. @= { if (un->bg) { if (un->bg->w > un->mapsize_x) un->mapsize_x = un->bg->w; if (un->bg->h > un->mapsize_y) un->mapsize_y = un->bg->h; } } @* Portability Code In this section we will define different ways to do things that are not portable among our target operating systems. The aim of this section is to make it easier to write code elsewhere, hopefully isolating nonportable code. @ For the moment, we are using |recv| everywhere, as |read| seems to be unavailable on Windows. We will leave the code that uses |read| around in case we find any reasons to switch back to it on Unix. @= @; @ @= { int read_len; int got_input = 0; int keep_reading = 1; VERBOSE("-=> recv cycle.\n"); while (keep_reading) { VERBOSE("-=> recv\n"); read_len = recv(con->fd, con->buffer + con->buflen, con->bufsiz - con->buflen, 0); VERBOSE("<=- recv\n"); switch (read_len) { case SOCKET_ERROR: switch (SOCKET_ERRNO()) { case SOCKET_CALL_INTR: break; @ if (con->state == MAT_STATE_PLAYING) MESSAGE_FROM(con, "has gone netdead"); mat_connection_free(con, MMP_SERVER_CLOSE_SYSERROR, strerror(SOCKET_ERRNO())); return; @ keep_reading = 0; break; default: fprintf(stderr, "%s: %s\n", program_name, strerror(errno)); exit(EXIT_FAILURE); } break; case 0: keep_reading = 0; break; default: ASSERT(read_len > 0); got_input = 1; con->buflen += read_len; con->buffer[con->buflen] = 0; } } VERBOSE("<=- recv cycle\n"); if (!got_input) return; } @ Here goes a list of errors when we try to read from a socket that mean the connection was closed. @= #ifdef WSAECONNRESET case WSAECONNRESET: #endif #ifdef WSAESHUTDOWN case WSAESHUTDOWN: #endif #ifdef WSAENETRESET case WSAENETRESET: #endif #ifdef ECONNRESET case ECONNRESET: #endif #ifdef EPIPE case EPIPE: #endif @ Here we add a list of all the errors that happen when no more input is available and we try to read from a socket. @= #ifdef EAGAIN case EAGAIN: #endif #ifdef WSAEWOULDBLOCK # if WSAEWOULDBLOCK != EAGAIN case WSAEWOULDBLOCK: # endif #endif #ifdef EWOULDBLOCK # if EWOULDBLOCK != EAGAIN case EWOULDBLOCK: # endif #endif @ In the following code we call |read| to fill the buffer of player |p| with incomming data. The following situations are possible: \item{$\bullet$} \bf Error |EINTR| takes place.\rm If the call was interrupted by a signal, we try again. This is very unlikely since the socket is non-blocking, but you never know. \item{$\bullet$} \bf Error |EAGAIN| takes place or |read| returns |0|.\rm This means no more data is available to be read. We leave the slot as it is and return. \item{$\bullet$} \bf Error |ECONNRESET| or |EPIPE| takes place.\rm If the remote server closes the connection, we mark the request as either failed or successful. \item{$\bullet$} \bf No error is detected.\rm The data was read, we do nothing in this case. \item{$\bullet$} \bf An unknown error is detected.\rm Since \.{Matanza} doesnt know how to handle the error, it terminates. @= { int read_len; do { VERBOSE("-=> read\n"); read_len = read(con->fd, con->buffer + con->buflen, con->bufsiz - con->buflen); VERBOSE("<=- read\n"); } while (read_len == -1 && errno == EINTR); switch (read_len) { case -1: switch (errno) { #ifdef ECONNRESET case ECONNRESET: #endif #ifdef EPIPE case EPIPE: #endif VERBOSE("read failed: connection closed\n"); if (con->state == MAT_STATE_PLAYING) MESSAGE_FROM(con, "has gone netdead"); mat_connection_free(con, MMP_SERVER_CLOSE_SYSERROR, strerror(errno)); return; case EAGAIN: VERBOSE("no more data is available\n"); return; default: fprintf(stderr, "%s: %s\n", program_name, strerror(errno)); exit(EXIT_FAILURE); } break; case 0: VERBOSE("no more data is available\n"); return; } VERBOSE("read data [len:%d]\n", read_len); con->buflen += read_len; con->buffer[con->buflen] = 0; } @ Windows and BeOS lack usleep. We need to find alternatives on them. @= #if HAVE_USLEEP # define USLEEP_GENERIC(x) \ { VERBOSE("-=> usleep\n"); usleep(x); VERBOSE("<=- usleep\n"); } #elif HAVE_SNOOZE_UNTIL # define USLEEP_GENERIC(x) USLEEP_SNOOZE_UNTIL(x) #elif HAVE_SLEEP # define USLEEP_GENERIC(x) \ { VERBOSE("-=> Sleep(%d)\n", x / 1000); Sleep(x / 1000); VERBOSE("<=- Sleep\n"); } #else # error Could not find way to implement USLEEP_GENERIC. #endif @ @d USLEEP_SNOOZE_UNTIL(xusec) { bigtime_t wake_at; status_t status; wake_at = system_time() + xusec; VERBOSE("-=> snooze_until cycle\n"); do { VERBOSE("-=> snooze_until\n"); status = snooze_until(wake_at, B_SYSTEM_TIMEBASE); VERBOSE("<=- snooze_until\n"); } while (status == EINTR); VERBOSE("<=- snooze_until cycle\n"); } @ Here we define |SOCKET_CLOSE_GENERIC| depending on the operating system we are being compiled on. @= #if HAVE_CLOSESOCKET # define SOCKET_CLOSE_GENERIC(s) closesocket(s) #else # define SOCKET_CLOSE_GENERIC(s) close(s) #endif @ Here we check to see how can get we get the current millisecond. @= #if HAVE_SYSTEM_TIME # ifdef B_SYSTEM_TIMEBASE # ifdef EINTR # define HAVE_SYSTEM_TIME_CONST 1 # else # define HAVE_SYSTEM_TIME_CONST 0 # endif # else # define HAVE_SYSTEM_TIME_CONST 0 # endif #else # define HAVE_SYSTEM_TIME_CONST 0 #endif /* If you get an error on the following line, there are some include files * missing. Basically, we are on BeOS but we can't get B_SYSTEM_TIMEBASE or * EINTR. */ #if __BEOS__ # ifndef EINTR # error Missing header files for BeOS: EINTR undefined # endif # ifndef B_SYSTEM_TIMEBASE # error Missing header files for BeOS: B_SYSTEM_TIMEBASE undefined # endif #endif #if HAVE_SYSTEM_TIME # define GETMICROSECOND_GENERIC(xx) GETMICROSECOND_SYSTEM_TIME(xx) #elif HAVE_GETTIMEOFDAY # define GETMICROSECOND_GENERIC(xx) GETMICROSECOND_GETTIMEOFDAY(xx) #elif HAVE_GETTICKCOUNT # define GETMICROSECOND_GENERIC(xx) GETMICROSECOND_GETTICKCOUNT(xx) #else # error Could not find a way to implement GETMICROSECOND_GENERIC. #endif @ @d GETMICROSECOND_SYSTEM_TIME(xx) { xx = (unsigned long) system_time(); } @ @d GETMICROSECOND_GETTICKCOUNT(xx) { xx = (unsigned long) GetTickCount() * 1000; } @ @d GETMICROSECOND_GETTIMEOFDAY(xx) { struct timeval st; gettimeofday(&st, NULL); xx = (unsigned long) (st.tv_sec * 1000000 + st.tv_usec); } @ Here we check to see how can we make the socket nonblocking and execute the appropriate code. @= #if HAVE_SETSOCKOPT # ifdef SOL_SOCKET # ifdef SO_NONBLOCK # define HAVE_SETSOCKOPT_NONBLOCK 1 # else # define HAVE_SETSOCKOPT_NONBLOCK 0 # endif # else # define HAVE_SETSOCKOPT_NONBLOCK 0 # endif #else # define HAVE_SETSOCKOPT_NONBLOCK 0 #endif #if HAVE_FCNTL # ifdef F_GETFL # ifdef F_SETFL # ifdef O_NONBLOCK # define HAVE_FCNTL_NONBLOCK 1 # else # define HAVE_FCNTL_NONBLOCK 0 # endif # else # define HAVE_FCNTL_NONBLOCK 0 # endif # else # define HAVE_FCNTL_NONBLOCK 0 # endif #else # define HAVE_FCNTL_NONBLOCK 0 #endif #if HAVE_SETSOCKOPT_NONBLOCK # define NONBLOCKING_GENERIC(result) NONBLOCKING_SETSOCKOPT(result) #elif HAVE_IOCTLSOCKET # define NONBLOCKING_GENERIC(result) NONBLOCKING_IOCTLSOCKET(result) #elif HAVE_FCNTL_NONBLOCK # define NONBLOCKING_GENERIC(result) NONBLOCKING_FCNTL(result) #else # error Could not find a way to implement NONBLOCKING_GENERIC. #endif @ @d NONBLOCKING_IOCTLSOCKET(result) { int dummy = 1; VERBOSE("ioctlsocket [fd:%d][option:FIONBIO]\n", result); if (ioctlsocket(result, FIONBIO, &dummy) == SOCKET_ERROR) { /* TODO: Make sure it's ok to call strerror like this. */ fprintf(stderr, "%s: ioctlsocket: %s\n", strerror(SOCKET_ERRNO())); exit(EXIT_FAILURE); } } @d NONBLOCKING_SETSOCKOPT(result) { char on = 1; VERBOSE("setsockopt [fd:%d][option:SO_NONBLOCK]\n", result); if (setsockopt(result, SOL_SOCKET, SO_NONBLOCK, (void *) &on, sizeof(char)) == -1) { fprintf(stderr, "%s: setsockopt: %s\n", program_name, strerror(errno)); exit(EXIT_FAILURE); } } @ @d NONBLOCKING_FCNTL(result) { int opts; VERBOSE("fcntl [fd:%d][option:O_NONBLOCK]\n", result); opts = fcntl(result, F_GETFL); if (opts < 0) { fprintf(stderr, "%s: fcntl: %s\n", program_name, strerror(errno)); exit(EXIT_FAILURE); } opts = (opts | O_NONBLOCK); if (fcntl(result, F_SETFL, opts) < 0) { fprintf(stderr, "%s: fcntl: %s\n", program_name, strerror(errno)); exit(EXIT_FAILURE); } } @ @= MatSocketT mat_listen ( int port ); @ @= MatSocketT mat_listen ( int port ) { struct sockaddr_in in; MatSocketT result; int on = 1; VERBOSE("Listening on port %d...", port); fflush(stdout); memset(&in, 0, sizeof(struct sockaddr_in)); in.sin_family = AF_INET; in.sin_addr.s_addr = INADDR_ANY; in.sin_port = htons(port); #if HAVE_WSASOCKET result = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, 0); #else result = socket(AF_INET, SOCK_STREAM, 0); #endif if (result == SOCKET_ERROR) { @; exit(EXIT_FAILURE); } #if HAVE_SETSOCKOPT # ifdef SOL_SOCKET # ifdef SO_REUSEADDR VERBOSE("setsockopt [fd:%d][option:SO_REUSEADDR]\n", result); setsockopt(result, SOL_SOCKET, SO_REUSEADDR, (void *) &on, sizeof(on)); # endif # endif #endif if (bind(result, (struct sockaddr*)&in, sizeof(struct sockaddr_in)) == SOCKET_ERROR) { fprintf(stderr, "%s: bind: %s\n", program_name, strerror(SOCKET_ERRNO())); exit(EXIT_FAILURE); } if (listen(result, 10) == SOCKET_ERROR) { exit(EXIT_FAILURE); fprintf(stderr, "%s: listen: %s\n", program_name, strerror(SOCKET_ERRNO())); } /* Make socket nonblocking. */ NONBLOCKING_GENERIC(result); VERBOSE(" Done\n"); return result; } @ There seems to be no portable way of describing an error. On Windows, we have to check for every individual error. We only check for those we think might happen. @= #if WIN32 switch (SOCKET_ERRNO()) { case WSAEMFILE: fprintf(stderr, "%s: socket: No more socket descriptors are available.\n", program_name); break; default: fprintf(stderr, "%s: socket: Unknown error (code %d)\n", program_name, SOCKET_ERRNO()); } #else fprintf(stderr, "%s: socket: %s\n", program_name, strerror(SOCKET_ERRNO())); #endif @ Portability information goes here. @= #ifdef WIN32 # include #else /* !WIN32 */ # ifdef HAVE_CONFIG_H # include # else /* !HAVE_CONFIG_H */ # define PACKAGE "matanza" # define VERSION "{Unknown-Version}" # endif /* !HAVE_CONFIG_H */ #endif /* !WIN32 */ @ /* Here we find out a way to build nonblocking sockets. */ @ /* Here we find out a way to get current millisecond. */ @ /* Here we find out how to close a socket. */ @ /* Here we find out how to sleep for a given time in microseconds. */ @ /* In windows, the type SOCKET is used for sockets. int is used everywhere * else. In this program, we use MatSocketT. Here we define it as * appropriate. */ #ifdef WIN32 #define MatSocketT SOCKET #else /* ! WIN32 */ #define MatSocketT int #endif /* ! WIN32 */ /* Windows returns SOCKET_ERROR when an error with a socket operation takes * place. UNIX returns -1. Windows forces us to use SOCKET_ERROR * everywhere. */ #ifndef WIN32 #define SOCKET_ERROR -1 #endif /* To get the reason why a socket call failed we simply look errno in UNIX. * On Windows, we are forced to call WSAGetLastError. We define SOCKET_ERRNO * appropriately. */ #ifdef WIN32 #define SOCKET_ERRNO() WSAGetLastError() #else #define SOCKET_ERRNO() errno #endif /* On UNIX, when a call is interrupted by a signal, SOCKET_ERRNO() returns * EINTR. On Windows, SOCKET_ERRNO() returns WSAEINTR. We define the * constant SOCKET_CALL_INTR to the appropriate value. */ #ifdef WIN32 # define SOCKET_CALL_INTR WSAEINTR #else # define SOCKET_CALL_INTR EINTR #endif #ifndef MAX # define MAX(x,y) ((x)>(y)?(x):(y)) #endif #ifndef MIN # define MIN(x,y) ((x)<(y)?(x):(y)) #endif @ On Windows we need to call WSAStartup() before any sockets-related functions. @= { #if HAVE_WSASTARTUP WORD ver; WSADATA data; int err; ver = MAKEWORD(2, 2); err = WSAStartup(ver, &data); if (err != 0) { fprintf(stderr, "%s: WSAStartup: Initialization failed.\n", program_name); exit(EXIT_FAILURE); } #endif } @* Socket output functions. In this section we will define three functions useful to perform buffered output to sockets. In earlier versions, we used fdopen and the C library's fprintf and similar functions. It turned out it wasn't very portable so we had to write our replacement functions. |mat_printf| works like a printf, but only accepts the |%c| and |%s| format options. It has a restriction on the maximum number of strings that can be print on a given call. |mat_write| works like a fwrite. |mat_flush| calls |send| to send the contents of the buffer through the socket. It is harmless to call |mat_flush| when the buffer is empty: it checks for said condition and does nothing if it evaluates to true. @= int mat_printf ( MatConnection *con, char *format, ... ); int mat_write ( MatConnection *con, void *buffer, size_t len ); int mat_out_flush ( MatConnection *con ); @ I think SOCKET_CALL_INTR will never happened on non-blocking sockets, but lets be safe. @= int mat_out_flush ( MatConnection *con ) { int retval; ASSERT(con); if (con->out_len == 0) return 1; ASSERT(con->out_buf); #ifdef MSG_NOSIGNAL # define MAT_SEND_FLAGS MSG_NOSIGNAL #else # define MAT_SEND_FLAGS 0 #endif send_retry: VERBOSE("-=> send\n"); retval = send(con->fd, con->out_buf, con->out_len, MAT_SEND_FLAGS); VERBOSE("<=- send\n"); if (retval == SOCKET_ERROR) { switch (SOCKET_ERRNO()) { case SOCKET_CALL_INTR: goto send_retry; case EPIPE: #ifdef WSAECONNRESET # if WSAECONNRESET != EPIPE case WSAECONNRESET: # endif #endif #ifdef WSAECONNABORTED # if WSAECONNABORTED != EPIPE case WSAECONNABORTED: # endif #endif #ifdef ECONNABORTED # if ECONNABORTED case ECONNABORTED: # endif #endif VERBOSE("send failed: connection closed\n"); return 0; case EAGAIN: #ifdef EWOULDBLOCK # if EWOULDBLOCK != EAGAIN case EWOULDBLOCK: # endif #endif #ifdef WSAEWOULDBLOCK # if WSAEWOULDBLOCK != EAGAIN case WSAEWOULDBLOCK: # endif #endif VERBOSE("send failed: player lagging\n"); con->info.t.clean = 0; break; default: fprintf(stderr, "%s: send: Unknown error (code %d)\n", program_name, SOCKET_ERRNO()); exit(EXIT_FAILURE); } } VERBOSE("send successful\n"); con->out_len = 0; return 1; } @ @= int mat_write ( MatConnection *con, void *buffer, size_t len ) { @; memcpy(con->out_buf + con->out_len, buffer, len); con->out_len += len; return 1; } @ @= int mat_printf ( MatConnection *con, char *format, ... ) { int slen[10]; int len; ASSERT(con); ASSERT(format); @; @; @; return 1; } @ @= { char *write_buf; int strcur = 0; va_list arg; write_buf = con->out_buf + con->out_len; va_start(arg, format); while (*format) if (*format == '%') { switch (*(++format)) { case '%': *(write_buf++) = *format; break; case 'd': write_buf += sprintf(write_buf, "%d", va_arg(arg, int)); break; case 'c': *(write_buf++) = (char) va_arg(arg, int); break; case 's': memcpy(write_buf, va_arg(arg, char *), slen[strcur]); write_buf += slen[strcur ++]; break; default: ASSERT(0); } format++; } else *(write_buf++) = *(format++); va_end(arg); ASSERT(write_buf >= con->out_buf); con->out_len = write_buf - con->out_buf; ASSERT(con->out_len >= 0); } @ @= { int nlen; nlen = con->out_len + len; if (nlen >= con->out_siz) { char *nbuf; int nsiz; nsiz = 2048 + nlen; nbuf = realloc(con->out_buf, nsiz); if (!nbuf) { fprintf(stderr, "%s: realloc: %s\n", program_name, strerror(errno)); exit(EXIT_FAILURE); } VERBOSE("Resized buffer: %d\n", nsiz); con->out_buf = nbuf; con->out_siz = nsiz; } } @ @= { va_list arg; char *tmp; int strcur = 0; char dummy_c; int dummy_d; va_start(arg, format); len = 0; tmp = format; while (*tmp) if (*(tmp++) == '%') switch (*(tmp++)) { case '%': len ++; break; case 'd': dummy_d = va_arg(arg, int); len += 10; break; case 'c': len ++; dummy_c = (char) va_arg(arg, int); break; case 's': /* If you get an assert fail in next line, increase the length of slen. */ ASSERT(strcur < sizeof(slen) / sizeof(int)); slen[strcur] = strlen(va_arg(arg, char *)); len += slen[strcur++]; break; default: ASSERT(0); } else len ++; va_end(arg); } @* Here we will use a structure to efficently keep track of what machines are subscribed to what universes. It has to perform the following operations as fast as possible: - Return a list of all the machines in a given universe. - Return a list of all the universes for a given machine. - Get rid of all the subscriptions for a given machine. - Get rid off a given subscription for one universe for one machine. @= int mat_sub_add ( MatConnection *m, MatUniverse *un ); void mat_sub_machine_rm ( MatConnection *m ); @ @= typedef struct MatSub MatSub; @ The natural solution for this is a doubly linked list that can be traversed by the universe (to get all the machines in a universe) or by the machine (to get all the machines in a universe). |m_prev| and |m_next| point to the node for the previous and next subscription for the current machine. Actually, not the next node but the next node in the current list in the hash of subscriptions for the machine. |u_prev| and |u_next| point to the node for the previous and next subscription for the current universe. |m| and |u| point to the current machine and universe. @= struct MatSub { MatConnection *m; MatSub *m_prev; MatSub *m_next; MatUniverse *u; MatSub *u_prev; MatSub *u_next; }; @ Since we want to be able to erase a subscription for one machine and universe, lets make a hash for all the subscriptions in a given machine. The code in this major section assumes that it is included in every machine as the field |subs|. We use an incredibly small value for the hash size since, for the moment, we only support one universe. TODO: Once support for multiple universes is added, increase the size of the hash. @d MAT_SUB_MACHINE_HASH_SIZE 1 @= typedef MatSub *MatSubMachine [MAT_SUB_MACHINE_HASH_SIZE]; @ Lets make a function to get rid of one given subscription. This function is only called by code inside this section. |s| is the subscription you want to get rid off. |hf| is the result of applying the hashing function to the universe's id. @= void mat_sub_rm ( MatSub *s, int hf ); @ And now the actual implementation. @d MAT_SUB_RM_U(s) { if (s->u_prev) s->u_prev->u_next = s->u_next; else s->u->subs = s->u_next; if (s->u_next) s->u_next->u_prev = s->u_prev; } @= void mat_sub_rm ( MatSub *s, int hf ) { if (s->m_prev) s->m_prev->m_next = s->m_next; else s->m->info.m.subs[hf] = s->m_next; if (s->m_next) s->m_next = s->m_prev; MAT_SUB_RM_U(s); free(s); } @ Now lets make a function to get rid of all the subscriptions of a given machine. @= void mat_sub_machine_rm ( MatConnection *m ) { MatSub *c; int i; ASSERT(m->state == MAT_STATE_MACHINE); for (i = 0; i < MAT_SUB_MACHINE_HASH_SIZE; i ++) { c = m->info.m.subs[i]; while (c) { MatSub *tmp; MAT_SUB_RM_U(c); tmp = c; c = tmp->m_next; free(tmp); } } } @ And now lets make a function that subscribes a machine to a universe (depending on its id). @= int mat_sub_add ( MatConnection *m, MatUniverse *un ) { MatSub *c; int pos; c = malloc(sizeof(MatSub)); if (!c) return 0; c->u = un; c->m = m; c->u_prev = NULL; c->u_next = un->subs; if (un->subs) un->subs->u_prev = c; un->subs = c; pos = un->id % MAT_SUB_MACHINE_HASH_SIZE; c->m_prev = NULL; c->m_next = m->info.m.subs[pos]; if (m->info.m.subs[pos]) m->info.m.subs[pos]->m_prev = c; m->info.m.subs[pos] = c; return 1; } @ Lets now make a macro to initialize the subscription of a machine. @d MAT_SUB_MACHINE_INIT(xm) { int mat_sub_machine_init = 0; while (mat_sub_machine_init < MAT_SUB_MACHINE_HASH_SIZE) xm->info.m.subs[mat_sub_machine_init++] = NULL; } @* Trigonometry Functions During program execution, we will need the sine and cosine of the normal angles. Rather than calculate them everytime, we will calculate them on all the standard angles (from 0 to |arg_ang|) and hold the results in the variables |mat_cos| and |mat_sin|. @= static double *mat_cos; static double *mat_sin; @ Here we calculate the values for all the angles we are interested on. @= { int i; mat_cos = malloc(sizeof(double) * arg_ang); mat_sin = malloc(sizeof(double) * arg_ang); if (!mat_cos || !mat_sin) { fprintf(stderr, "%s: %s\n", program_name, strerror(errno)); exit(EXIT_FAILURE); } for (i = 0; i < arg_ang; i ++) { double ang; ang = PI * 2.0 * (double) i / (double) arg_ang; mat_cos[i] = cos(ang); mat_sin[i] = sin(ang); } } @ Finally, here we destroy all our caches. @= { free(mat_cos); free(mat_sin); } @* Images In this section we will put the high-level code that deals with images. We define the following functions (actually, we define more, but all the others are meant to be used internally by the code in this section): @d MAT_IMAGE_DRAW_ST(xs, xsh, xi, startx, starty, mat_stdpal, arg_bg_adj, alpha) mat_image_draw(xs, xsh, xi, 0, 0, 0, 0, startx, starty, mat_stdpal, arg_bg_adj, alpha) @d MAT_IMAGE_DRAW_DY(xs, xsh, xi, x, y, p, startx, starty, xadj) mat_image_draw(xs, xsh, xi, x, y, xsh->sp_x - p->sp_x, xsh->sp_y - p->sp_y, startx, starty, p->pal, xadj, p->alpha) @= void mat_image_draw ( MatConnection *self, MatMovingObj *ship, MatImage *img, int x, int y, double sp_x, double sp_y, int startx, int starty, unsigned char *pal, int adj, double alpha ); void mat_image_optimize ( MatImage *img ); @ Here we draw |img| in coordinates |x| and |y| to player |self|. |pos_x| and |pos_y| hold the beginning of the image, relative to the beginning of the screen of the player. |sp| is the speed squared. @= void mat_image_draw ( MatConnection *self, MatMovingObj *ship, MatImage *img, int x, int y, double sp_x, double sp_y, int startx, int starty, unsigned char *pal, int adj, double alpha ) { double height, width, sp; double rate_x, rate_y, pos_x, pos_y; int size_x, size_y; ASSERT(ship); ASSERT(ship->type == MAT_MOVING_OBJ_SHIP); ASSERT(img); ASSERT(img->w > 0); ASSERT(img->h > 0); ASSERT(ship->info.player.world_wi > 0); ASSERT(ship->info.player.imgwi > 0); if (alpha <= 0.0) return; if (ship->info.player.world_wi != ship->info.player.imgwi) { rate_x = (double)ship->info.player.world_wi / (double)ship->info.player.imgwi; width = (double)img->w / rate_x; } else { rate_x = 1; width = img->w; } ASSERT(rate_x > 0); ASSERT(ship->info.player.world_he > 0); ASSERT(ship->info.player.imghe > 0); if (ship->info.player.world_he != ship->info.player.imghe) { rate_y = (double)ship->info.player.world_he / (double)ship->info.player.imghe; height = (double)img->h / rate_y; } else { rate_y = 1; height = img->h; } ASSERT(rate_y > 0); ASSERT(img->w <= ship->un->mapsize_x); ASSERT(img->h <= ship->un->mapsize_y); if (adj) { double rate_x, rate_y; size_x = img->w; size_y = img->h; rate_x = (double) size_x / (double) ship->un->mapsize_x; rate_y = (double) size_y / (double) ship->un->mapsize_y; x = (double) x * rate_x; y = (double) y * rate_y; startx = (double) startx * rate_x; starty = (double) starty * rate_y; } else { size_x = ship->un->mapsize_x; size_y = ship->un->mapsize_y; } ASSERT(img->w <= size_x); ASSERT(img->h <= size_y); ASSERT(0 <= startx); ASSERT(startx < size_x); ASSERT(0 <= starty); ASSERT(starty < size_y); ASSERT(0 <= x); ASSERT(x < size_x); ASSERT(0 <= y); ASSERT(y < size_y); pos_x = x - startx; pos_y = y - starty; ASSERT(-size_x < (int)pos_x); ASSERT(-size_y < (int)pos_y); ASSERT((int)pos_x < size_x); ASSERT((int)pos_y < size_y); if (0 < (int)pos_x) pos_x -= size_x; if (0 < (int)pos_y) pos_y -= size_y; ASSERT((int)pos_x <= 0); ASSERT((int)pos_y <= 0); ASSERT(-size_x < (int)pos_x); ASSERT(-size_y < (int)pos_y); sp = sp_x * sp_x + sp_y * sp_y; if (!arg_motion_blur || sp < 1.0 / (double) STEPS_MOVEMENT) { if (alpha >= 1.0) @@; else @@; } else @@; } @ @= { int steps; int i; sp = sqrt(sp); steps = sp * STEPS_MOVEMENT; alpha = alpha / (double) steps; for (i = 0; i < steps; i ++) { @; @; } } @ @= { #define MAT_IMAGE_DRAW_ALPHA(xx, yy) \ mat_image_draw_alpha(self, ship, img, xx, yy, rate_x, rate_y, width, height, pal, alpha) ASSERT((int)pos_x <= 0); ASSERT((int)pos_y <= 0); ASSERT(-size_x < (int)pos_x); ASSERT(-size_y < (int)pos_y); if (0 < (int) pos_x + img->w) { if (0 < (int) pos_y + img->h) MAT_IMAGE_DRAW_ALPHA(pos_x, pos_y ); if ((int) pos_y + size_y < ship->info.player.world_he) MAT_IMAGE_DRAW_ALPHA(pos_x, pos_y + size_y); } if ((int) pos_x + size_x < ship->info.player.world_wi) { if (0 < (int) pos_y + img->h) MAT_IMAGE_DRAW_ALPHA(pos_x + size_x, pos_y ); if ((int) pos_y + size_y < ship->info.player.world_he) MAT_IMAGE_DRAW_ALPHA(pos_x + size_x, pos_y + size_y); } } @ @= { ASSERT(-size_x < (int) pos_x); ASSERT((int) pos_x <= 0); ASSERT(ABS(sp_x) <= size_x); pos_x += sp_x; ASSERT(2 * -size_x < (int) pos_x); ASSERT((int) pos_x <= size_x); if ((int) pos_x <= -size_x) pos_x += size_x; else if (0 < (int)pos_x) pos_x -= size_x; ASSERT(-size_x < (int) pos_x); ASSERT((int) pos_x <= 0); ASSERT(-size_y < (int) pos_y); ASSERT((int) pos_y <= 0); ASSERT(ABS(sp_y) <= size_y); pos_y += sp_y; ASSERT(2 * -size_y < (int) pos_y); ASSERT((int) pos_y <= size_y); if ((int) pos_y <= -size_y) pos_y += size_y; else if (0 < (int)pos_y) pos_y -= size_y; ASSERT(-size_y < (int) pos_y); ASSERT((int) pos_y <= 0); } @ @= { #define MAT_IMAGE_DRAW_FAST(xx, yy) \ mat_image_draw_fast(self, ship, img, xx, yy, rate_x, rate_y, width, height, pal) if (0 < (int)pos_x + img->w) { if (0 < (int)pos_y + img->h) MAT_IMAGE_DRAW_FAST(pos_x, pos_y ); if ((int)pos_y + size_y < ship->info.player.world_he) MAT_IMAGE_DRAW_FAST(pos_x, pos_y + size_y); } if ((int)pos_x + size_x < ship->info.player.world_wi) { if (0 < (int)pos_y + img->h) MAT_IMAGE_DRAW_FAST(pos_x + size_x, pos_y ); if ((int)pos_y + size_y < ship->info.player.world_he) MAT_IMAGE_DRAW_FAST(pos_x + size_x, pos_y + size_y); } } @ @= void mat_image_draw_fast ( MatConnection *self, MatMovingObj *ship, MatImage *img, double pos_x, double pos_y, double rate_x, double rate_y, double width, double height, unsigned char *pal ); void mat_image_draw_alpha ( MatConnection *self, MatMovingObj *ship, MatImage *img, double pos_x, double pos_y, double rate_x, double rate_y, double width, double height, unsigned char *pal, double alpha ); @ @= void mat_image_draw_alpha ( MatConnection *self, MatMovingObj *ship, MatImage *img, double pos_x, double pos_y, double rate_x, double rate_y, double width, double height, unsigned char *pal, double alpha ) { int col_x, col_y, col, i, j; double x1, y1; MatShip *sh; ASSERT(width > 0); ASSERT(height > 0); ASSERT(rate_x > 0); ASSERT(rate_y > 0); ASSERT(ship); ASSERT(ship->type == MAT_MOVING_OBJ_SHIP); if (rate_x != 1) pos_x = (double)pos_x / rate_x; if (rate_y != 1) pos_y = (double)pos_y / rate_y; ASSERT(0 < pos_x + width ); ASSERT(0 < pos_y + height); ASSERT(pos_x >= 0 || -pos_x < width ); ASSERT(pos_y >= 0 || -pos_y < height); if (pos_x < 0) x1 = -pos_x; else x1 = 0; if (pos_y < 0) y1 = -pos_y; else y1 = 0; ASSERT(x1 >= 0); ASSERT(y1 >= 0); ASSERT(x1 < width); ASSERT(y1 < height); if ((int)pos_x + (int)width >= ship->info.player.imgwi) width = ship->info.player.imgwi - (int)pos_x - 1; ASSERT((int)pos_x + (int)width < ship->info.player.imgwi); if ((int)pos_y + (int)height >= ship->info.player.imghe) height = ship->info.player.imghe - (int)pos_y - 1; ASSERT((int)pos_y + (int)height < ship->info.player.imghe); sh = &ship->info.player; for (i = (int)y1; i < (int)height; i ++) for (j = (int)x1; j < (int)width; j ++) { col = 0; for (col_y = 0; col_y < rate_y && (int)(i*rate_y) + col_y < img->h; col_y ++) for (col_x = 0; col_x < rate_x && (int)(j*rate_x) + col_x < img->w; col_x ++) col += pal[(int)img->img[((int)(i*rate_y)+col_y)*img->w+((int)(j*rate_x)+col_x)]]; ASSERT(0 < col_x); ASSERT(0 < col_y); ASSERT(col >= 0); if (col > 0) MAT_GRAPH_DRAW_ALPHA(self, sh, (int)pos_x+j, (int)pos_y+i, col/(col_y*col_x), alpha); } } @ @= void mat_image_draw_fast ( MatConnection *self, MatMovingObj *ship, MatImage *img, double pos_x, double pos_y, double rate_x, double rate_y, double width, double height, unsigned char *pal ) { int col_x, col_y, col, i, j; double x1, y1; MatShip *sh; ASSERT(width > 0); ASSERT(height > 0); ASSERT(rate_x > 0); ASSERT(rate_y > 0); ASSERT(ship); ASSERT(ship->type == MAT_MOVING_OBJ_SHIP); if (rate_x != 1) pos_x = (double)pos_x / rate_x; if (rate_y != 1) pos_y = (double)pos_y / rate_y; ASSERT(0 < pos_x + width ); ASSERT(0 < pos_y + height); ASSERT(pos_x >= 0 || -pos_x < width ); ASSERT(pos_y >= 0 || -pos_y < height); if (pos_x < 0) x1 = -pos_x; else x1 = 0; if (pos_y < 0) y1 = -pos_y; else y1 = 0; ASSERT(x1 >= 0); ASSERT(y1 >= 0); ASSERT(x1 < width); ASSERT(y1 < height); if ((int)pos_x + (int)width >= ship->info.player.imgwi) width = ship->info.player.imgwi - (int)pos_x - 1; ASSERT((int)pos_x + (int)width < ship->info.player.imgwi); if ((int)pos_y + (int)height >= ship->info.player.imghe) height = ship->info.player.imghe - (int)pos_y - 1; ASSERT((int)pos_y + (int)height < ship->info.player.imghe); sh = &ship->info.player; for (i = (int)y1; i < (int)height; i ++) for (j = (int)x1; j < (int)width; j ++) { col = 0; for (col_y = 0; col_y < rate_y && (int)(i*rate_y) + col_y < img->h; col_y ++) for (col_x = 0; col_x < rate_x && (int)(j*rate_x) + col_x < img->w; col_x ++) col += pal[(int)img->img[((int)(i*rate_y)+col_y)*img->w+((int)(j*rate_x)+col_x)]]; ASSERT(0 < col_x); ASSERT(0 < col_y); ASSERT(col >= 0); if (col > 0) MAT_GRAPH_DRAW(self, sh, (int)pos_x+j, (int)pos_y+i, col/(col_y*col_x)); } } @ Receives an array of |arg_ang| images and optimizes it to reduce memory consumption. @= void mat_image_optimize ( MatImage *img ) { int xbeg, xend, ybeg, yend; @; @; } @ @d MAT_IMAGE_REDUCTION_H(var, start, modify) { int blank = 1, ang, i; for (var = start; blank; var += modify) for (ang = 0; ang < arg_ang; ang ++) for (i = 0; i < img[0].w; i ++) if (img[ang].img[var * img[ang].w + i] != ' ') blank = 0, i = img[ang].w, ang = arg_ang; var -= modify; } @d MAT_IMAGE_REDUCTION_X(var, start, modify) { int blank = 1, ang, i; for (var = start; blank; var += modify) for (ang = 0; ang < arg_ang; ang ++) for (i = ybeg; i < yend; i ++) if (img[ang].img[i * img[ang].w + var] != ' ') blank = 0, i = img[ang].h, ang = arg_ang; var -= modify; } @= { MAT_IMAGE_REDUCTION_H(ybeg, 0, 1); ASSERT(0 <= ybeg); ASSERT(ybeg < img[0].h); MAT_IMAGE_REDUCTION_H(yend, img[0].h - 1, -1); ASSERT(ybeg < yend); ASSERT(yend < img[0].h); MAT_IMAGE_REDUCTION_X(xbeg, 0, 1); ASSERT(0 <= xbeg); ASSERT(xbeg < img[0].w); MAT_IMAGE_REDUCTION_X(xend, img[0].w - 1, -1); ASSERT(xbeg < xend); ASSERT(xend < img[0].w); } @ @= { int ang; for (ang = 0; ang < arg_ang; ang ++) { char *tmp; int pos = 0, x, y; for (y = ybeg; y < yend; y ++) for (x = xbeg; x < xend; x ++) img[ang].img[pos ++] = img[ang].img[y * img[ang].w + x]; ASSERT(pos == (xend - xbeg) * (yend - ybeg)); /* This is supposed to never fail, but if it fails, we can fix it. */ tmp = realloc(img[ang].img, pos); if (tmp) img[ang].img = tmp; img[ang].h = yend - ybeg; img[ang].w = xend - xbeg; } } @* Aliens System @= typedef struct MatSmartObj MatSmartObj; typedef struct MatSmartObjType MatSmartObjType; @ @= struct MatSmartObjType { char *name; MatImage *img; void (*function) (MatMovingObj *obj); }; struct MatSmartObj { int type; }; @ @= MatSmartObjType mat_objects[] = { { "Woozka", NULL, &mat_object_woozka }, { "Kashka", NULL, &mat_object_kashka } }; @ @= void mat_object_woozka ( MatMovingObj *obj ); void mat_object_kashka ( MatMovingObj *obj ); @ @= void mat_object_kashka ( MatMovingObj *obj ) { MatMovingObj *dst; int dist_x, dist_dx, dist_dy, dist_y, dist_total; double sp_x, sp_y; ASSERT(obj); ASSERT(obj->un); ASSERT(obj->type == MAT_MOVING_OBJ_SMART); ASSERT(obj->info.smart.type == 1); ASSERT(!obj->crash); if (!obj->un->players_real || obj->un->updates % 5) return; @; ASSERT(dst); sp_x = (double) dist_dx * (double) dist_x / (double) (dist_x + dist_y); sp_y = (double) dist_dy * (double) dist_y / (double) (dist_x + dist_y); printf("Shoting: %fx%f\n", sp_x, sp_y); mat_bullet_new(obj, 0, sp_x, sp_y, 0); } @ @= void mat_object_woozka ( MatMovingObj *obj ) { MatMovingObj *dst; int dist_x, dist_dx, dist_dy, dist_y, dist_total; ASSERT(obj); ASSERT(obj->un); ASSERT(obj->type == MAT_MOVING_OBJ_SMART); ASSERT(obj->info.smart.type == 0); ASSERT(!obj->crash); if (!obj->un->players_real) return; @; ASSERT(dst); @; ASSERT(!obj->crash); } @ @= { double des_sp, des_sp_x, des_sp_y; #if 0 printf("[x:%d][y:%d][sx:%f][sy:%f]\n", dist_dx * dist_x, dist_dy * dist_y, obj->sp_x, obj->sp_y); #endif if (dist_x != 0 || dist_y != 0) { double dist_sum; dist_sum = (double) dist_x + dist_y; des_sp_x = obj->sp_x + 0.01 * (double) dist_dx * (double) dist_x / dist_sum; des_sp_y = obj->sp_y + 0.01 * (double) dist_dy * (double) dist_y / dist_sum; des_sp = sqrt(des_sp_x * des_sp_x + des_sp_y * des_sp_y); if (des_sp * 3 < arg_speed_max) { obj->sp = des_sp; obj->sp_x = des_sp_x; obj->sp_y = des_sp_y; } else { double tsp; /* TODO: Code here probably has bugs. */ tsp = (double) arg_speed_max / 3; obj->sp_x = tsp * (double) dist_dx * (double) dist_x / dist_sum; obj->sp_y = tsp * (double) dist_dy * (double) dist_y / dist_sum; obj->sp = sqrt(obj->sp_x * obj->sp_x + obj->sp_y * obj->sp_y); } } } @ @= { MatMovingObj *sh; ASSERT(obj->un->players_head); dst = NULL; #if 0 printf("[woozka: [x:%x][y:%x]]\n", obj->pos_x, obj->pos_y); #endif for (sh = obj->un->players_head; sh; sh = sh->nexttype) { int x, y, dx, dy, total; @; total = x * x + y * y; if (!dst || total < dist_total) { #if 0 printf("[obj: [x:%x][y:%x]]\n", sh->pos_x, sh->pos_y); #endif dst = sh; dist_total = total; dist_x = x; dist_dx = -dx; dist_y = y; dist_dy = -dy; } } } @ @d MAT_SMART_OBJ_ADD_WOOZKA(xun) MAT_SMART_OBJ_ADD(xun, 0) @d MAT_SMART_OBJ_ADD_KASHKA(xun) MAT_SMART_OBJ_ADD(xun, 1) @d MAT_SMART_OBJ_ADD(xun, xtype) { MatMovingObj *obj; obj = malloc(sizeof(MatMovingObj)); if (!obj) { fprintf(stderr, "%s: %s\n", program_name, strerror(errno)); exit(EXIT_FAILURE); } obj->type = MAT_MOVING_OBJ_SMART; obj->rm_next = NULL; obj->refs = 1; ASSERT(mat_ast[1]); obj->img = mat_ast[1]; obj->pal = mat_ship_palette[0]; obj->ang = 0; obj->sp_ang = 0; obj->info.smart.type = xtype; obj->crash = 0; obj->draw = 1; obj->alpha = 1; obj->alpha_mod = NULL; obj->un = xun; obj->nexttype = xun->smart_objs; obj->prevtype = NULL; if (xun->smart_objs) xun->smart_objs->prevtype = obj; xun->smart_objs = obj; obj->sp = obj->sp_x = obj->sp_y = 0; obj->pos_x = (double) (rand() % xun->mapsize_x); obj->pos_y = (double) (rand() % xun->mapsize_y); ADD_MOVING_OBJ(obj, xun); } @ @= { MatMovingObj *obj; for (obj = un->smart_objs; obj; obj = obj->nexttype) { ASSERT(obj->type == MAT_MOVING_OBJ_SMART); ASSERT(obj->info.smart.type < sizeof(mat_objects) / sizeof(MatSmartObjType)); mat_objects[obj->info.smart.type].function(obj); } } /* TODO: Add smart_obj_handler */ @* XML Code @= { XML_Parser *prs; FILE *in; char buf[BUFSIZ]; int done; @; @; prs = XML_ParserCreate(NULL); XML_SetUserData(prs, un); XML_SetElementHandler(prs, mat_xml_start, mat_xml_end); do { size_t len; len = fread(buf, 1, sizeof(buf), in); done = len < sizeof(buf); if (!XML_Parse(prs, buf, len, done)) { fprintf(stderr, "%s: %s:%d: %s\n", program_name, un->path, XML_GetCurrentLineNumber(prs), XML_ErrorString(XML_GetErrorCode(prs))); exit(EXIT_FAILURE); } } while (!done); XML_ParserFree(prs); @; } @ @= void mat_xml_start ( void *data, const char *name, const char **atts ); void mat_xml_end ( void *data, const char *name ); @ @= void mat_xml_start (void *data, const char *name, const char **atts) { MatUniverse *un = data; if (!strcmp(name, "Universe")) @@; else if (!strcmp(name, "Location")) @@; else { fprintf(stderr, "%s: %s: %s: Unknown tag\n", program_name, un->path, name); exit(EXIT_FAILURE); } } @ @= { int i, color = 0; MatLocation *l; l = malloc(sizeof(MatLocation)); if (!l) { fprintf(stderr, "%s: %s\n", program_name, strerror(errno)); exit(EXIT_FAILURE); } memcpy(l, &mat_location_default, sizeof(MatLocation)); for (i = 0; atts[i]; i += 2) if (!strcmp(atts[i], "color")) color = atoi(atts[i + 1]); else if (!strcmp(atts[i], "shipcrash")) l->crash[MAT_MOVING_OBJ_SHIP] = strcmp(atts[i + 1], "yes") ? 0 : 1; else if (!strcmp(atts[i], "asteroidcrash")) l->crash[MAT_MOVING_OBJ_AST] = strcmp(atts[i + 1], "yes") ? 0 : 1; else if (!strcmp(atts[i], "health")) l->health = atoi(atts[i + 1]); else if (!strcmp(atts[i], "shipmove")) l->move[MAT_MOVING_OBJ_SHIP] = atof(atts[i + 1]); else { fprintf(stderr, "%s: %s: Unknown attribute for \n", program_name, atts[i]); exit(EXIT_FAILURE); } if (color < 0 || color > 255) { fprintf(stderr, "%s: %d: Invalid color specified\n", program_name, color); exit(EXIT_FAILURE); } un->location[color] = l; } @ @= { int i; for (i = 0; atts[i]; i += 2) if (!strcmp(atts[i], "mapsizex")) un->mapsize_x = atoi(atts[i + 1]); else if (!strcmp(atts[i], "mapsizey")) un->mapsize_y = atoi(atts[i + 1]); else if (!strcmp(atts[i], "name")) ; else if (!strcmp(atts[i], "background")) un->bg = mat_png_load(atts[i + 1]); else if (!strcmp(atts[i], "mask")) un->mask = mat_png_load(atts[i + 1]); else if (!strcmp(atts[i], "dots")) un->dots = strcmp(atts[i + 1], "no") ? 1 : 0; else if (!strcmp(atts[i], "health")) un->health = atoi(atts[i + 1]); else { fprintf(stderr, "%s: %s: Unknown attribute for \n", program_name, atts[i]); exit(EXIT_FAILURE); } } @ @= void mat_xml_end (void *userData, const char *name) { } @ @= in = fopen(un->path, "r"); if (!in) { fprintf(stderr, "%s: %s: %s\n", program_name, un->path, strerror(errno)); exit(EXIT_FAILURE); } @* Alpha Transparency We want to make it possible to draw objects transparently. This is used mostly for the times when they are appearing. |alpha| goes from 0 to 1, 0 meaning the object will be invisible and 1 meaning it will be solid. If |alpha_mod| is not |NULL|, it will be called once for every turn and is supposed to modify the alpha parameter. @= double alpha; void (*alpha_mod) (MatMovingObj *); @ @= void mat_alpha_mod_ship_appear ( MatMovingObj *s ); void mat_alpha_mod_ship_disappear ( MatMovingObj *s ); @ @= void mat_alpha_mod_ship_appear ( MatMovingObj *s ) { s->alpha += 0.01; if (s->alpha >= 1.0) { s->alpha_mod = NULL; s->crash = 1; } } @ @= void mat_alpha_mod_ship_disappear ( MatMovingObj *s ) { s->alpha -= 0.01; if (s->alpha <= 0) { s->alpha_mod = NULL; } } matanza-0.13/COPYING0000644000175000017500000004311007107673450014303 0ustar boradminboradmin GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 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. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. matanza-0.13/xmltok_impl.h0000644000175000017500000000123107254521711015751 0ustar boradminboradmin/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd See the file copying.txt for copying permission. */ enum { BT_NONXML, BT_MALFORM, BT_LT, BT_AMP, BT_RSQB, BT_LEAD2, BT_LEAD3, BT_LEAD4, BT_TRAIL, BT_CR, BT_LF, BT_GT, BT_QUOT, BT_APOS, BT_EQUALS, BT_QUEST, BT_EXCL, BT_SOL, BT_SEMI, BT_NUM, BT_LSQB, BT_S, BT_NMSTRT, BT_COLON, BT_HEX, BT_DIGIT, BT_NAME, BT_MINUS, BT_OTHER, /* known not to be a name or name start character */ BT_NONASCII, /* might be a name or name start character */ BT_PERCNT, BT_LPAR, BT_RPAR, BT_AST, BT_PLUS, BT_COMMA, BT_VERBAR }; #include matanza-0.13/AUTHORS0000644000175000017500000000005307155041701014306 0ustar boradminboradminAlejandro Forero Cuervo matanza-0.13/utf8tab.h0000644000175000017500000000334407254453527015007 0ustar boradminboradmin/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd See the file copying.txt for copying permission. */ /* 0x80 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, /* 0x84 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, /* 0x88 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, /* 0x8C */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, /* 0x90 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, /* 0x94 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, /* 0x98 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, /* 0x9C */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, /* 0xA0 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, /* 0xA4 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, /* 0xA8 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, /* 0xAC */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, /* 0xB0 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, /* 0xB4 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, /* 0xB8 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, /* 0xBC */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, /* 0xC0 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, /* 0xC4 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, /* 0xC8 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, /* 0xCC */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, /* 0xD0 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, /* 0xD4 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, /* 0xD8 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, /* 0xDC */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, /* 0xE0 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3, /* 0xE4 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3, /* 0xE8 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3, /* 0xEC */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3, /* 0xF0 */ BT_LEAD4, BT_LEAD4, BT_LEAD4, BT_LEAD4, /* 0xF4 */ BT_LEAD4, BT_NONXML, BT_NONXML, BT_NONXML, /* 0xF8 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, /* 0xFC */ BT_NONXML, BT_NONXML, BT_MALFORM, BT_MALFORM, matanza-0.13/xmldef.h0000644000175000017500000000222007254521711014670 0ustar boradminboradmin/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd See the file copying.txt for copying permission. */ #include #ifdef XML_WINLIB #define WIN32_LEAN_AND_MEAN #define STRICT #include #define malloc(x) HeapAlloc(GetProcessHeap(), 0, (x)) #define calloc(x, y) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (x)*(y)) #define free(x) HeapFree(GetProcessHeap(), 0, (x)) #define realloc(x, y) HeapReAlloc(GetProcessHeap(), 0, x, y) #define abort() /* as nothing */ #else /* not XML_WINLIB */ #include #endif /* not XML_WINLIB */ /* This file can be used for any definitions needed in particular environments. */ /* Mozilla specific defines */ #ifdef MOZILLA_CLIENT #include "nspr.h" #define malloc(x) PR_Malloc((size_t)(x)) #define realloc(x, y) PR_Realloc((x), (size_t)(y)) #define calloc(x, y) PR_Calloc((x),(y)) #define free(x) PR_Free(x) #if PR_BYTES_PER_INT != 4 #define int int32 #endif /* Enable Unicode string processing in expat. */ #ifndef XML_UNICODE #define XML_UNICODE #endif /* Enable external parameter entity parsing in expat */ #ifndef XML_DTD #define XML_DTD 1 #endif #endif /* MOZILLA_CLIENT */ matanza-0.13/acconfig.h0000644000175000017500000000010007155051232015151 0ustar boradminboradmin/* Define to `int' if <> doesn't define it. */ #undef socklen_t matanza-0.13/xmltok.h0000644000175000017500000002347207254521711014743 0ustar boradminboradmin/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd See the file copying.txt for copying permission. */ #ifndef XmlTok_INCLUDED #define XmlTok_INCLUDED 1 #ifdef __cplusplus extern "C" { #endif #ifndef XMLTOKAPI #define XMLTOKAPI /* as nothing */ #endif /* The following token may be returned by XmlContentTok */ #define XML_TOK_TRAILING_RSQB -5 /* ] or ]] at the end of the scan; might be start of illegal ]]> sequence */ /* The following tokens may be returned by both XmlPrologTok and XmlContentTok */ #define XML_TOK_NONE -4 /* The string to be scanned is empty */ #define XML_TOK_TRAILING_CR -3 /* A CR at the end of the scan; might be part of CRLF sequence */ #define XML_TOK_PARTIAL_CHAR -2 /* only part of a multibyte sequence */ #define XML_TOK_PARTIAL -1 /* only part of a token */ #define XML_TOK_INVALID 0 /* The following tokens are returned by XmlContentTok; some are also returned by XmlAttributeValueTok, XmlEntityTok, XmlCdataSectionTok */ #define XML_TOK_START_TAG_WITH_ATTS 1 #define XML_TOK_START_TAG_NO_ATTS 2 #define XML_TOK_EMPTY_ELEMENT_WITH_ATTS 3 /* empty element tag */ #define XML_TOK_EMPTY_ELEMENT_NO_ATTS 4 #define XML_TOK_END_TAG 5 #define XML_TOK_DATA_CHARS 6 #define XML_TOK_DATA_NEWLINE 7 #define XML_TOK_CDATA_SECT_OPEN 8 #define XML_TOK_ENTITY_REF 9 #define XML_TOK_CHAR_REF 10 /* numeric character reference */ /* The following tokens may be returned by both XmlPrologTok and XmlContentTok */ #define XML_TOK_PI 11 /* processing instruction */ #define XML_TOK_XML_DECL 12 /* XML decl or text decl */ #define XML_TOK_COMMENT 13 #define XML_TOK_BOM 14 /* Byte order mark */ /* The following tokens are returned only by XmlPrologTok */ #define XML_TOK_PROLOG_S 15 #define XML_TOK_DECL_OPEN 16 /* */ #define XML_TOK_NAME 18 #define XML_TOK_NMTOKEN 19 #define XML_TOK_POUND_NAME 20 /* #name */ #define XML_TOK_OR 21 /* | */ #define XML_TOK_PERCENT 22 #define XML_TOK_OPEN_PAREN 23 #define XML_TOK_CLOSE_PAREN 24 #define XML_TOK_OPEN_BRACKET 25 #define XML_TOK_CLOSE_BRACKET 26 #define XML_TOK_LITERAL 27 #define XML_TOK_PARAM_ENTITY_REF 28 #define XML_TOK_INSTANCE_START 29 /* The following occur only in element type declarations */ #define XML_TOK_NAME_QUESTION 30 /* name? */ #define XML_TOK_NAME_ASTERISK 31 /* name* */ #define XML_TOK_NAME_PLUS 32 /* name+ */ #define XML_TOK_COND_SECT_OPEN 33 /* */ #define XML_TOK_CLOSE_PAREN_QUESTION 35 /* )? */ #define XML_TOK_CLOSE_PAREN_ASTERISK 36 /* )* */ #define XML_TOK_CLOSE_PAREN_PLUS 37 /* )+ */ #define XML_TOK_COMMA 38 /* The following token is returned only by XmlAttributeValueTok */ #define XML_TOK_ATTRIBUTE_VALUE_S 39 /* The following token is returned only by XmlCdataSectionTok */ #define XML_TOK_CDATA_SECT_CLOSE 40 /* With namespace processing this is returned by XmlPrologTok for a name with a colon. */ #define XML_TOK_PREFIXED_NAME 41 #ifdef XML_DTD #define XML_TOK_IGNORE_SECT 42 #endif /* XML_DTD */ #ifdef XML_DTD #define XML_N_STATES 4 #else /* not XML_DTD */ #define XML_N_STATES 3 #endif /* not XML_DTD */ #define XML_PROLOG_STATE 0 #define XML_CONTENT_STATE 1 #define XML_CDATA_SECTION_STATE 2 #ifdef XML_DTD #define XML_IGNORE_SECTION_STATE 3 #endif /* XML_DTD */ #define XML_N_LITERAL_TYPES 2 #define XML_ATTRIBUTE_VALUE_LITERAL 0 #define XML_ENTITY_VALUE_LITERAL 1 /* The size of the buffer passed to XmlUtf8Encode must be at least this. */ #define XML_UTF8_ENCODE_MAX 4 /* The size of the buffer passed to XmlUtf16Encode must be at least this. */ #define XML_UTF16_ENCODE_MAX 2 typedef struct position { /* first line and first column are 0 not 1 */ unsigned long lineNumber; unsigned long columnNumber; } POSITION; typedef struct { const char *name; const char *valuePtr; const char *valueEnd; char normalized; } ATTRIBUTE; struct encoding; typedef struct encoding ENCODING; struct encoding { int (*scanners[XML_N_STATES])(const ENCODING *, const char *, const char *, const char **); int (*literalScanners[XML_N_LITERAL_TYPES])(const ENCODING *, const char *, const char *, const char **); int (*sameName)(const ENCODING *, const char *, const char *); int (*nameMatchesAscii)(const ENCODING *, const char *, const char *, const char *); int (*nameLength)(const ENCODING *, const char *); const char *(*skipS)(const ENCODING *, const char *); int (*getAtts)(const ENCODING *enc, const char *ptr, int attsMax, ATTRIBUTE *atts); int (*charRefNumber)(const ENCODING *enc, const char *ptr); int (*predefinedEntityName)(const ENCODING *, const char *, const char *); void (*updatePosition)(const ENCODING *, const char *ptr, const char *end, POSITION *); int (*isPublicId)(const ENCODING *enc, const char *ptr, const char *end, const char **badPtr); void (*utf8Convert)(const ENCODING *enc, const char **fromP, const char *fromLim, char **toP, const char *toLim); void (*utf16Convert)(const ENCODING *enc, const char **fromP, const char *fromLim, unsigned short **toP, const unsigned short *toLim); int minBytesPerChar; char isUtf8; char isUtf16; }; /* Scan the string starting at ptr until the end of the next complete token, but do not scan past eptr. Return an integer giving the type of token. Return XML_TOK_NONE when ptr == eptr; nextTokPtr will not be set. Return XML_TOK_PARTIAL when the string does not contain a complete token; nextTokPtr will not be set. Return XML_TOK_INVALID when the string does not start a valid token; nextTokPtr will be set to point to the character which made the token invalid. Otherwise the string starts with a valid token; nextTokPtr will be set to point to the character following the end of that token. Each data character counts as a single token, but adjacent data characters may be returned together. Similarly for characters in the prolog outside literals, comments and processing instructions. */ #define XmlTok(enc, state, ptr, end, nextTokPtr) \ (((enc)->scanners[state])(enc, ptr, end, nextTokPtr)) #define XmlPrologTok(enc, ptr, end, nextTokPtr) \ XmlTok(enc, XML_PROLOG_STATE, ptr, end, nextTokPtr) #define XmlContentTok(enc, ptr, end, nextTokPtr) \ XmlTok(enc, XML_CONTENT_STATE, ptr, end, nextTokPtr) #define XmlCdataSectionTok(enc, ptr, end, nextTokPtr) \ XmlTok(enc, XML_CDATA_SECTION_STATE, ptr, end, nextTokPtr) #ifdef XML_DTD #define XmlIgnoreSectionTok(enc, ptr, end, nextTokPtr) \ XmlTok(enc, XML_IGNORE_SECTION_STATE, ptr, end, nextTokPtr) #endif /* XML_DTD */ /* This is used for performing a 2nd-level tokenization on the content of a literal that has already been returned by XmlTok. */ #define XmlLiteralTok(enc, literalType, ptr, end, nextTokPtr) \ (((enc)->literalScanners[literalType])(enc, ptr, end, nextTokPtr)) #define XmlAttributeValueTok(enc, ptr, end, nextTokPtr) \ XmlLiteralTok(enc, XML_ATTRIBUTE_VALUE_LITERAL, ptr, end, nextTokPtr) #define XmlEntityValueTok(enc, ptr, end, nextTokPtr) \ XmlLiteralTok(enc, XML_ENTITY_VALUE_LITERAL, ptr, end, nextTokPtr) #define XmlSameName(enc, ptr1, ptr2) (((enc)->sameName)(enc, ptr1, ptr2)) #define XmlNameMatchesAscii(enc, ptr1, end1, ptr2) \ (((enc)->nameMatchesAscii)(enc, ptr1, end1, ptr2)) #define XmlNameLength(enc, ptr) \ (((enc)->nameLength)(enc, ptr)) #define XmlSkipS(enc, ptr) \ (((enc)->skipS)(enc, ptr)) #define XmlGetAttributes(enc, ptr, attsMax, atts) \ (((enc)->getAtts)(enc, ptr, attsMax, atts)) #define XmlCharRefNumber(enc, ptr) \ (((enc)->charRefNumber)(enc, ptr)) #define XmlPredefinedEntityName(enc, ptr, end) \ (((enc)->predefinedEntityName)(enc, ptr, end)) #define XmlUpdatePosition(enc, ptr, end, pos) \ (((enc)->updatePosition)(enc, ptr, end, pos)) #define XmlIsPublicId(enc, ptr, end, badPtr) \ (((enc)->isPublicId)(enc, ptr, end, badPtr)) #define XmlUtf8Convert(enc, fromP, fromLim, toP, toLim) \ (((enc)->utf8Convert)(enc, fromP, fromLim, toP, toLim)) #define XmlUtf16Convert(enc, fromP, fromLim, toP, toLim) \ (((enc)->utf16Convert)(enc, fromP, fromLim, toP, toLim)) typedef struct { ENCODING initEnc; const ENCODING **encPtr; } INIT_ENCODING; int XMLTOKAPI XmlParseXmlDecl(int isGeneralTextEntity, const ENCODING *enc, const char *ptr, const char *end, const char **badPtr, const char **versionPtr, const char **encodingNamePtr, const ENCODING **namedEncodingPtr, int *standalonePtr); int XMLTOKAPI XmlInitEncoding(INIT_ENCODING *, const ENCODING **, const char *name); const ENCODING XMLTOKAPI *XmlGetUtf8InternalEncoding(void); const ENCODING XMLTOKAPI *XmlGetUtf16InternalEncoding(void); int XMLTOKAPI XmlUtf8Encode(int charNumber, char *buf); int XMLTOKAPI XmlUtf16Encode(int charNumber, unsigned short *buf); int XMLTOKAPI XmlSizeOfUnknownEncoding(void); ENCODING XMLTOKAPI * XmlInitUnknownEncoding(void *mem, int *table, int (*conv)(void *userData, const char *p), void *userData); int XMLTOKAPI XmlParseXmlDeclNS(int isGeneralTextEntity, const ENCODING *enc, const char *ptr, const char *end, const char **badPtr, const char **versionPtr, const char **encodingNamePtr, const ENCODING **namedEncodingPtr, int *standalonePtr); int XMLTOKAPI XmlInitEncodingNS(INIT_ENCODING *, const ENCODING **, const char *name); const ENCODING XMLTOKAPI *XmlGetUtf8InternalEncodingNS(void); const ENCODING XMLTOKAPI *XmlGetUtf16InternalEncodingNS(void); ENCODING XMLTOKAPI * XmlInitUnknownEncodingNS(void *mem, int *table, int (*conv)(void *userData, const char *p), void *userData); #ifdef __cplusplus } #endif #endif /* not XmlTok_INCLUDED */ matanza-0.13/shipreal.c0000644000175000017500000011256707250032606015227 0ustar boradminboradmin#define MAT_SHIPSIZE_X 116 #define MAT_SHIPSIZE_Y 54 #if 0 char *ship= " " " " " " " " " " " ** " " ** " " ** " " ** " " ** " " **** " " **** " " ****** " " ******** " " ************ " " ************** " " XXX **************** XXX " " XXXXXXX **************** XXXXXXX " " XXXXXXX ********..******** XXXXXXX " " XXXXXXX *******....******* XXXXXXX " " XXXXXXX *******......******* XXXXXXX " " XXXXXXX *******......******* XXXXXXX " " XXXXXXX 1 ******........****** 2 XXXXXXX " " XXXXXXX 1 *******........******* 2 XXXXXXX " " XXXXXXX 1 *******........******* 2 XXXXXXX " " XXXXXXX 111 *******........******* 222 XXXXXXX " " XXXXXXX 111 ********........******** 222 XXXXXXX " " XXXXXXX*******************************........*******************************XXXXXXX " " XXXXXXX********************************......********************************XXXXXXX " " XXXXXXX*********************************....*********************************XXXXXXX " " XXXXXXX 111 ***********..*********** 222 XXXXXXX " " XXXXXXX 111 ************************ 222 XXXXXXX " " XXXXXXX 111 ************************ 222 XXXXXXX " " XXXXXXX 111 ************************ 222 XXXXXXX " " XXXXXXX 111 ************************ 222 XXXXXXX " " XXXXXXX 111 ************************ 222 XXXXXXX " " XXXXXXX 111 ************************ 222 XXXXXXX " " XXXXXXX 111 ************************ 222 XXXXXXX " " XXXXXXX 111 ************************ 222 XXXXXXX " " XXXXXXX 111 ************************ 222 XXXXXXX " " XXXXXXX 111 ************************ 222 XXXXXXX " " XXXXXXX 111 ************************ 222 XXXXXXX " " XXXXXXX 111 ************************ 222 XXXXXXX " " XXXXXXX 111 ************************ 222 XXXXXXX " " XXXXXXX**********************************************************************XXXXXXX " " XXXXXXX**********************************************************************XXXXXXX " " XXXXXXX**********************************************************************XXXXXXX " " XXXXXXX**********************************************************************XXXXXXX " " XXXXXXX 111 ************************ 222 XXXXXXX " " XXXXXXX 111 ************************ 222 XXXXXXX " " XXXXXXX 1 ******************** 2 XXXXXXX " " XXX **************** XXX " " " " " " "; #endif char *arg_ship_graphic = " " " XX " " XX " " XX " " XX " " XX " " XX " " XXXX " " XXXXXXXX " " *XXXXXXXXXX* " " *XXXXXXXXXX* " " **XXXXXXXXXX** " " **XXXXXXXXXX** " " **XXXX..XXXX** " " ***XXX....XXX*** " " ****XX......XX**** " " *****XX......XX***** " " ******X........X****** " " *******X........X******* " " 1 ********X........X******** 2 " " 1 *********X........X********* 2 " " 1 **********X........X********** 2 " " 111 ***********X........X*********** 222 " " 111 ************XX......XX************ 222 " " 111 *************XXX....XXX************* 222 " " 111 **************XXXX..XXXX************** 222 " " 111 ***************XXXXXXXXXX*************** 222 " " 111 ****************XXXXXXXXXX**************** 222 " " 111 *****************XXXXXXXXXX***************** 222 " " 111 ******************XXXXXXXXXX****************** 222 " " 111 *******************XXXXXXXXXX******************* 222 " " 111********************XXXXXXXXXX********************222 " " 11*********************XXXXXXXXXX*********************22 " " 1**********************XXXXXXXXXX**********************2 " " ***********************XXXXXXXXXX*********************** " " ************************XXXXXXXXXX************************ " " *************************XXXXXXXXXX************************* " " **************************XXXXXXXXXX************************** " " ***************************XXXXXXXXXX*************************** " " ***************************XXXXXXXXXX*************************** " " ************ **XXXXXXXXXX** ************ " " ******** XXXXXXXX ******** " " *******11 XXXXXX 22******* " " **** 111 XXXXXX 222 **** " " ** 111 XXXXXX 222 ** " " * 111 XXXXXX 222 * " " 111 XXXXXX 222 " " 111 XXXX 222 " " 111 XXXX 222 " " 111 *XXXX* 222 " " 1 ***XXXX*** 2 " " ********XXXX******** " " XX " " " " "; #define MAT_MISSILESIZE_X 63 #define MAT_MISSILESIZE_Y 36 char *mat_graph_missile[] = { " " " " " " " " " " " " " " " " " " " " " " " " " X " " X " " XXX " " XXX " " XXX " " XXX " " XXX " " XXX " " XXX " " XXX " " XXX " " XXX " " XXX " " X " " " " " " " " " " " " " " " " " " " " " " ", " " " " " X " " X " " X " " XXX " " XXX " " XXX " " XXX " " XXX " " XXX " " XXX " " XXX " " XXX " " XXX " " XXX " " XXX " " XXX " " XXX " " XXX " " XXX " " XXX " " XXX " " XXX " " XXX " " XXX " " XXX " " XXX " " XXX " " XXX " " XXX " " XXX " " XXX " " X " " " " " " ", " " " XXXXXXX " " XXXXXXXXX " " XXXXXXXXX " " XXXXXXXXXXX " " XXXXXXXXXXX " " XXXXXXXXXXX " " XXXXXXXXXXX " " XXXXXXXXXXX " " XXXXXXXXXXX " " XXXXXXXXXXX " " XXXXXXXXXXX " " XXXXXXXXXXX " " XXXXXXXXXXX " " XXXXXXXXXXX " " XXXXXXXXXXX " " XXXXXXXXXXX " " XXXXXXXXXXX " " XXXXXXXXXXX " " XXXXXXXXXXX " " XXXXXXXXXXX " " XXXXXXXXXXX " " XXXXXXXXXXX " " XXXXXXXXXXX " " XXXXXXXXXXX " " XXXXXXXXXXX " " XXXXXXXXXXX " " XXXXXXXXXXX " " XXXXXXXXXXX " " XXXXXXXXXXX " " XXXXXXXXXXX " " XXXXXXXXXXX " " XXXXXXXXXXX " " XXXXXXXXXXX " " XXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXX " }; #define MAT_AST_SIZE_X 90 #define MAT_AST_SIZE_Y 89 char *mat_graph_ast[] = { " " " " " " " " " " " " " " " " " XXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXX " " XXXXXX " " " " " " " " " " " " ", " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " XXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXX " " XXXXXXXXXXXXXXX " " XXXXXXXXXXXXX " " XXXXXXX " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " }; matanza-0.13/NEWS0000644000175000017500000001770007261765212013754 0ustar boradminboradminVersion 0.13: - We now call fork() and other standard stuff to make the process a daemon. Other changes in this direction are required (specially for logging things). - We now catch WSACONNRESET in Windows. It was causing us to exit before ("matanza: send: Unknown error (code 10054)"). - Added motion blur for objects that move too fast (speed is relative to the viewer). - Fixed crash when --ppc was 2. - Made it possible for a player to see the world as other players see it. - Added support for telnet's linemode kludge. Should fix problems with CRT and probably other telnet clients. - Made it possible to enable and disable verbose messages at runtime. Added a lot of verbosity that will hopefully help us find problems at certain platforms faster. - Now depending on whether MATANZA_VERBOSE, Matanza is compiled with all the verbose messages. If it is not enabled, it is compiled without them, which shrinks the file size. - Added a new image for a ship (shiptank.txt). - It is now possible to compile Matanza without asserts: just don't define MATANZA_ASSERT at compile time. - Made it possible to view the world as the other players. The commands `[' and `]' are used to change from the current player to the prev/next. - Fixed bug with some images for the ships: As they got rotated, some parts (corners) used to disappear. 17/Mar/2001 Version 0.12: - CPU optimizations for drawing images to players when the game is paused. - LibXML is no longer used. - Expat is now bundled with Matanza. It is now possible to load universes using it. - Initial support for simple monsters. - Significative memory optimizations. Images (which acocunted for most of the memory used by Matanza) are now taking around 16% of what they used to. For example, the images for the asteroids used to require 1001 kb and now take only 157. - Fixed a few memory leaks. - Fixed bug: The default maximing speed (arg_speed_max) was way too big. - Added initial code for simple monsters. - Fixed a bug with applying x/y scale rates to the direction of bullets. - Changed the way zooming works. Fixed a bug where the x/y scales would almost never match the x/y screen sizes, which caused problems that can be explained as having a square look like a rectangle. - Fixed a bug (I didn't think it was a bug, but it was reported as such) that caused the ship to rotate too fast at the beginning. Now it rotates slowly. Bug or not, this is an improvement. - Started to implement MMP, to allow programs to control ships remotely. It is still under development. - Hopefully fixed a bug that caused the screen to become full of trash when a player lagged for a significative time. - Lots of internal changes to make the implementation of MMP as efficient as possible, as well as to be able to support multiple universes in one instance of the server. - It is now possible to modify the ship's image at runtime (without recompiling Matanza). The `--ship-img' parameter allows you to specify the path to the image. See the `ship.txt' file for more details. This feature was suggested by Augusto Tamayo. - By Popular Demand, port to Microsoft Windows is complete. It should be considered beta. Please report any bugs. - Port to BeOS is complete. It should be considered beta. Please report any bugs. Thanks to Andrés Felipe Arguello for his useful input and testing during the porting process. - Fixed bug concerning the "Game Over" label when ppc is 2. - Made it possible for players to zoom in and out as they wish. `-' and `=' are used. When ppc is two, you can use `-', `=', `/' and `*'. - Command `w' now reports the lives left for every player. - When ppc is 2, the following commands are now supported: `z', `0', `p'. - When playing in air mode, collisions of players with asteroids and players among themselves are ignored. - Fixed assertion fails (6247). 15/Feb/2001 Version 0.11: - Fixed bug: when players lose, they are no longer shown in other players' radars. - Fixed a bug where sometimes the keyboard was set on limbo. - Added primite support for worlds. This depends on libxml. - The fire effect was finally fixed. - Support for JPEG image format was removed. "Perfection is reached, not when there is no longer anything to add, but when there is no longer anything to take away." -- Antoine de Saint-Exupery - Support for PNG files was added. "Everything should be made as simple as possible, but not simpler." -- Albert Einstein - It is now possible to quit during the game hitting `q' (and `Q'). 06/Jan/2001 Version 0.10: - Now bullets do hit asteroids. After some damage, they break into smaller asteroids. - We now draw the direction to reach asteroids. - It is now possible to control the ship using the arrow keys. - When no players are playing (or connected), Matanza now automatically pauses the game so it won't waste CPU cycles. - Now you can have two players per connection (parameter ppc). - Header file is no longer needed to compile Matanza. This was reported as a bug by Andrés Felipe Arguello, who is porting to Beos. - Fixed a bug that would make players seeing the fire effects (the stuff after the "Presents") see everything differently. - Support for loading the background image from a JPEG file was added. - Strong bandwidth optimizations made on the way output is sent to the players. - More command line arguments were added. 27/Sep/2000 Version 0.9: - Space mode (previously specified with `--space') is now the default. Use option `--air'. - Fixed assert (matanza.w:3501). - Added command line arguments `--asteroids' (specifies how many asteriods we draw), `--invisibility' (the maximum time the players can be invisible), `--no-radar' (doesn't show the directions to reach other players) and `--limits' (give edges to the world, rather than making it ``round'') where added. - When a player runs out of bullets of a given type, we let him now. - Default values for the maximum speed and angular speed were increased. - Improved the README. 18/Sep/2000 Version 0.8: - Added more navigation modes, specified using parameters `--brake', `--ang-speed-max', `--speed-max', `--fly-back' and `--space'. I was inspired by kasteroid. - Small optimizations. 17/Sep/2000 Version 0.7: - Fixed a few assertion fails. - Added teams mode, specified with parameters `--team', `--no-share' and `--teams-safe'. - Added command line argument `--password' to perform authentication. - When the command line arguments are not sane, we now fix them rather than refuse to run. - Added new type of missiles, shot with `n'. - Improved widgets of the main menu. - Maximum player's name increased to 8 characters. - Added more names to the list of initial random names. - Improved the messages sent to the players to remove redundancy. - Added command line argument `--no-chat' to remove that functionality. - Added parameter `--lives'. Apparently this change in version 0.5 got lost. 15/Sep/2000 Version 0.6: - Bug fixes. 12/Sep/2000 Version 0.5: - Now every player gets a random name from a list. - Now every player has many lives, specified with `--lifes'. - Fix for a bug for terminals with white background. - Fixes for assertion fails. 9/Sep/2000 Version 0.4: - Fixed bugs that were causing crashes (ASSERTs failed). - Added options --health, --mapsize-x and --mapsize-y. 8/Sep/2000 Version 0.3: - Fixed bug with telnet clients that send \r\n (eg. Windows'). - Added command line option --bold (there are some bugs with this). - Fixed bug with missiles. - Now we do draw the missiles. - Added command line options --imgheight and --imgwidth. Useful to zoom in/out. - Added command line argument --version. - Fixed compilation problem on BSDs (about getopt). Hopefully. 5/Sep/2000 Version 0.2: - Made it possible to shot bullets backwards. - Fixed bug about the counter of players. - The line at the bottom of the screen is now used. 4/Sep/2000 Version 0.1: - First distribution of Matanza. matanza-0.13/mkinstalldirs0000744000175000017500000000132207107673453016056 0ustar boradminboradmin#! /bin/sh # mkinstalldirs --- make directory hierarchy # Author: Noah Friedman # Created: 1993-05-16 # Public domain # $Id: mkinstalldirs,v 1.13 1999/01/05 03:18:55 bje Exp $ errstatus=0 for file do set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` shift pathcomp= for d do pathcomp="$pathcomp$d" case "$pathcomp" in -* ) pathcomp=./$pathcomp ;; esac if test ! -d "$pathcomp"; then echo "mkdir $pathcomp" mkdir "$pathcomp" || lasterr=$? if test ! -d "$pathcomp"; then errstatus=$lasterr fi fi pathcomp="$pathcomp/" done done exit $errstatus # mkinstalldirs ends here matanza-0.13/shiptank.txt0000644000175000017500000001166007255772265015647 0ustar boradminboradmin# This graphic must be 116 x 54 characters big. If you modify it and come # up with anything interesting, send it to so it gets # included with the next release. We are planning to distribute a big list # of ships and allow the players to choose from among them. # # For the moment, you must make sure the sizes and positions of the # missiles does -not- change. In the future, you'll be able to place them # anywhere. # # Lines begining with `#' get ignored. # # To try your new image, use the `--ship-img' argument when you run Matanza # (for example: matanza --ship-img ship.txt). # # By the way, to edit this file under Vim, you'll want to use :set nowrap # to have it not perform line wrapping. ** ** ** ** ** **** **** ****** ******** ************ ************** XXX **************** XXX XXXXXXX **************** XXXXXXX XXXXXXX ********..******** XXXXXXX XXXXXXX *******....******* XXXXXXX XXXXXXX *******......******* XXXXXXX XXXXXXX *******......******* XXXXXXX XXXXXXX 1 ******........****** 2 XXXXXXX XXXXXXX 1 *******........******* 2 XXXXXXX XXXXXXX 1 *******........******* 2 XXXXXXX XXXXXXX 111 *******........******* 222 XXXXXXX XXXXXXX 111 ********........******** 222 XXXXXXX XXXXXXX*******************************........*******************************XXXXXXX XXXXXXX********************************......********************************XXXXXXX XXXXXXX*********************************....*********************************XXXXXXX XXXXXXX 111 ***********..*********** 222 XXXXXXX XXXXXXX 111 ************************ 222 XXXXXXX XXXXXXX 111 ************************ 222 XXXXXXX XXXXXXX 111 ************************ 222 XXXXXXX XXXXXXX 111 ************************ 222 XXXXXXX XXXXXXX 111 ************************ 222 XXXXXXX XXXXXXX 111 ************************ 222 XXXXXXX XXXXXXX 111 ************************ 222 XXXXXXX XXXXXXX 111 ************************ 222 XXXXXXX XXXXXXX 111 ************************ 222 XXXXXXX XXXXXXX 111 ************************ 222 XXXXXXX XXXXXXX 111 ************************ 222 XXXXXXX XXXXXXX 111 ************************ 222 XXXXXXX XXXXXXX 111 ************************ 222 XXXXXXX XXXXXXX**********************************************************************XXXXXXX XXXXXXX**********************************************************************XXXXXXX XXXXXXX**********************************************************************XXXXXXX XXXXXXX**********************************************************************XXXXXXX XXXXXXX 111 ************************ 222 XXXXXXX XXXXXXX 111 ************************ 222 XXXXXXX XXXXXXX 1 ******************** 2 XXXXXXX XXX **************** XXX matanza-0.13/Makefile.am0000644000175000017500000000337207261765174015320 0ustar boradminboradmin## Process this file with automake to produce Makefile.in ## ## Copyright (C) 1999 Alejandro Forero Cuervo ## ## This file is part of HB. ## ## HB is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as ## published by the Free Software Foundation; either version 2, or ## (at your option) any later version. ## ## HB is distributed in the hope that it will be useful, but ## WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public ## License along with HB; see the file COPYING. If not, write ## to the Free Software Foundation, Inc., 59 Temple Place, Suite ## 330, Boston, MA 02111-1307 USA bin_PROGRAMS = matanza matanza-ai matanza_ai_SOURCES = \ ai.c \ getopt.h \ getopt.c \ getopt1.c EXTRA_matanza_ai_SOURCES = \ mmp.h matanza_SOURCES = \ matanza.c \ getopt.h \ getopt.c \ getopt1.c \ xmlparse.h xmlrole.h xmltok.h \ xmlparse.c xmlrole.c xmltok.c \ xmldef.h ascii.h asciitab.h iasciitab.h latin1tab.h nametab.h utf8tab.h BUILT_SOURCES = \ matanza.c \ ai.c EXTRA_matanza_SOURCES = \ shipreal.c \ mmp.h \ winconfig.h \ xmltok_impl.c \ xmltok_impl.h \ xmltok_ns.c matanza.c: matanza.w ctangle matanza.w ai.c: ai.w ctangle ai.w EXTRA_DIST = \ matanza.w \ ai.w \ TODO \ ship.txt \ shiptank.txt \ matanza.xml \ maze.png matanza-0.13/matanza.xml0000644000175000017500000000117407254523636015434 0ustar boradminboradmin matanza-0.13/ascii.h0000644000175000017500000000342707254453450014517 0ustar boradminboradmin/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd See the file copying.txt for copying permission. */ #define ASCII_A 0x41 #define ASCII_B 0x42 #define ASCII_C 0x43 #define ASCII_D 0x44 #define ASCII_E 0x45 #define ASCII_F 0x46 #define ASCII_G 0x47 #define ASCII_H 0x48 #define ASCII_I 0x49 #define ASCII_J 0x4A #define ASCII_K 0x4B #define ASCII_L 0x4C #define ASCII_M 0x4D #define ASCII_N 0x4E #define ASCII_O 0x4F #define ASCII_P 0x50 #define ASCII_Q 0x51 #define ASCII_R 0x52 #define ASCII_S 0x53 #define ASCII_T 0x54 #define ASCII_U 0x55 #define ASCII_V 0x56 #define ASCII_W 0x57 #define ASCII_X 0x58 #define ASCII_Y 0x59 #define ASCII_Z 0x5A #define ASCII_a 0x61 #define ASCII_b 0x62 #define ASCII_c 0x63 #define ASCII_d 0x64 #define ASCII_e 0x65 #define ASCII_f 0x66 #define ASCII_g 0x67 #define ASCII_h 0x68 #define ASCII_i 0x69 #define ASCII_j 0x6A #define ASCII_k 0x6B #define ASCII_l 0x6C #define ASCII_m 0x6D #define ASCII_n 0x6E #define ASCII_o 0x6F #define ASCII_p 0x70 #define ASCII_q 0x71 #define ASCII_r 0x72 #define ASCII_s 0x73 #define ASCII_t 0x74 #define ASCII_u 0x75 #define ASCII_v 0x76 #define ASCII_w 0x77 #define ASCII_x 0x78 #define ASCII_y 0x79 #define ASCII_z 0x7A #define ASCII_0 0x30 #define ASCII_1 0x31 #define ASCII_2 0x32 #define ASCII_3 0x33 #define ASCII_4 0x34 #define ASCII_5 0x35 #define ASCII_6 0x36 #define ASCII_7 0x37 #define ASCII_8 0x38 #define ASCII_9 0x39 #define ASCII_TAB 0x09 #define ASCII_SPACE 0x20 #define ASCII_EXCL 0x21 #define ASCII_QUOT 0x22 #define ASCII_AMP 0x26 #define ASCII_APOS 0x27 #define ASCII_MINUS 0x2D #define ASCII_PERIOD 0x2E #define ASCII_COLON 0x3A #define ASCII_SEMI 0x3B #define ASCII_LT 0x3C #define ASCII_EQUALS 0x3D #define ASCII_GT 0x3E #define ASCII_LSQB 0x5B #define ASCII_RSQB 0x5D #define ASCII_UNDERSCORE 0x5F matanza-0.13/maze.png0000644000175000017500000000674607254465362014734 0ustar boradminboradmin‰PNG  IHDRèèçªogAMA± üabKGDª#2 pHYs  ÒÝ~ütIMEÑ# Ûš‰ gIDATxÚíÜ1v! @A)O÷¿²R¤q±®vAž)SXüŸ²;Ž•þÏ~vYáÇ€ ‚: è 耠‚:ÌRiç·: è 耠‚:: 耠‚‚: 耠€ ‚: è 耠‚:: 耠‚‚: 耠€ ‚: è 耠‚:: 耠‚‚: 耠‚‚: 耠€ ‚: è 耠‚:: 耠‚‚: 耠€ ‚: è 耠‚:: 耠‚‚: 耠€ ‚: 耠€ [¨¶[É!ëð]áÎÌçž›ÐAt@ÐAAX¨¼²Ä ¾+Vð2™{Ž t@ÐAAt@Ð@ÐAtt@ÐAt@ÐAAt@Ð@Ðm: 耠‚‚: 耠€ ‚: è 耠‚:: 耠‚‚: 耠€ ‚: è 耠‚:: 耠‚‚: 耠€ ‚: 耠€ ‚: è 耠‚:: 耠‚‚: 耠€ ‚,V=xqyàÿ܃ל{§Ýs: 耠€ ‚: è 耠7+/q—´àžcBt@ÐAAt@Ð@ÐAtt@ÐAt@ÐAAt@Ð@Ðm: 耠‚‚: 耠€ ‚: è 耠‚:: 耠‚‚: 耠€ ‚: è 耠‚:: 耠‚‚: 耠€ ‚: 耠€ ‚: è 耠‚:: 耠‚‚: 耠€ {«¾øcÚˆˆˆ¶àž›ÐAt@ÐAAxBÙxoÊ«‰^„tÌ¿ç&tt@ÐAt@ÐAAt@Ð@ÐAtt@ÐAt@ÐAAt@Ð@ÐAtt@ÐAt@ÐAAt@ÐAAt@Ð@ÐAtt@ÐAt@ÐAAt@Ð@ÐAtt@ÐAt@ÐAAt@Ð@ÐAt@Ð@ÐAþEM^\;_çñ¡tlÛCé~àî›Ð` AAt@Ð@ÐAx5ú¥8¯|9p?ÖéÁë0¡‚:: 耠‚‚: 耠‚‚: 耠€ ‚: è 耠‚:: 耠‚‚: 耠€ ‚: è 耠‚:: 耠‚‚: 耠€ ‚: 耠€ ‚: è 耠‚:: 耠‚‚: 耠€ ‚: è 耠‚:: èÀmÊÀ{m ÀÝ7¡‚:: 耠‚‚:ð„ôÖ^úò¬|W`BAt@Ð@ÐAtt@ÐAt@ÐAAt@Ð@ÐAt@Ð@ÐAtt@ÐAt@ÐAAt@Ð@ÐAtt@ÐAt@ÐAAt@Ð@ÐAtt@ÐAtt@ÐAt@ÐAAt@Ð@ÐAtt@ÐAt@ÐAAt@Ð@ÐAtøBÙm`üE²?W¾+Lè 耠‚:: 耠‚_£®þèõøÓîÇVì=˜Ð@ÐAtt@ÐAt@ÐAAt@Ð@ÐAtt@ÐAÝ€ ‚: è 耠‚:: 耠‚‚: 耠€ ‚: è 耠‚:: 耠‚‚: 耠€ ‚: è 耠‚:: 耠‚:: 耠‚‚: 耠€ ‚: è 耠‚:: èÀb5e!í,·’¶`ûûáŒÀ„: 耠€ ‚: è èÀÆjò⼄u¯ô˜ÐAt@ÐAAt@Ð@ÐAtt@ÐAt@ÐAAt@Ð@ÐAtt@ÐAt@ÐAAt@ÐAAt@Ð@ÐAtt@ÐAt@ÐAAt@Ð@ÐAtt@ÐAt@ÐAAt@Ð@ÐAtt@ÐAt¢lÁ^Ú`BAt@Ð@ÐAtÀKq›I[€ t@ÐAAt@ÐAAt@Ð@ÐAtt@ÐAt@ÐAAt@Ð@ÐAtt@ÐAt@ÐAAt@Ð@ÐAtt@ÐAtt@ÐAt@ÐAAt@Ð@ÐAtt@ÐAt@ÐAAt@Ð@ÐAtt@Ѐ§Ôäŵ󅈈H[&t@ÐAt@ÐAAÎ2æ¥8/a`Bt@ÐAAt@Ð@ÐAtt@ÐAt@ÐAAt@Ð@ÐAtt@ÐAt@ÐAAt@Ð@ÐAtt@ÐAtt@ÐAt@ÐAAt@Ð@ÐAtt@ÐAt@ÐAAt@Ð@ÐAtt@ÐAt@ЀýØs-ò‘øàIEND®B`‚matanza-0.13/getopt1.c0000644000175000017500000001071207156225364015002 0ustar boradminboradmin/* getopt_long and getopt_long_only entry points for GNU getopt. Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98 Free Software Foundation, Inc. NOTE: The canonical source of this file is maintained with the GNU C Library. Bugs can be reported to bug-glibc@gnu.org. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H #include #endif #include "getopt.h" #if !defined __STDC__ || !__STDC__ /* This is a separate conditional since some stdc systems reject `defined (const)'. */ #ifndef const #define const #endif #endif #include /* Comment out all this code if we are using the GNU C Library, and are not actually compiling the library itself. This code is part of the GNU C Library, but also included in many other GNU distributions. Compiling and linking in this code is a waste when using the GNU C library (especially if it is a shared library). Rather than having every GNU program understand `configure --with-gnu-libc' and omit the object files, it is simpler to just do this in the source for each such file. */ #define GETOPT_INTERFACE_VERSION 2 #if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2 #include #if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION #define ELIDE_CODE #endif #endif #ifndef ELIDE_CODE /* This needs to come after some library #include to get __GNU_LIBRARY__ defined. */ #ifdef __GNU_LIBRARY__ #include #endif #ifndef NULL #define NULL 0 #endif int getopt_long (argc, argv, options, long_options, opt_index) int argc; char *const *argv; const char *options; const struct option *long_options; int *opt_index; { return _getopt_internal (argc, argv, options, long_options, opt_index, 0); } /* Like getopt_long, but '-' as well as '--' can indicate a long option. If an option that starts with '-' (not '--') doesn't match a long option, but does match a short option, it is parsed as a short option instead. */ int getopt_long_only (argc, argv, options, long_options, opt_index) int argc; char *const *argv; const char *options; const struct option *long_options; int *opt_index; { return _getopt_internal (argc, argv, options, long_options, opt_index, 1); } #endif /* Not ELIDE_CODE. */ #ifdef TEST #include int main (argc, argv) int argc; char **argv; { int c; int digit_optind = 0; while (1) { int this_option_optind = optind ? optind : 1; int option_index = 0; static struct option long_options[] = { {"add", 1, 0, 0}, {"append", 0, 0, 0}, {"delete", 1, 0, 0}, {"verbose", 0, 0, 0}, {"create", 0, 0, 0}, {"file", 1, 0, 0}, {0, 0, 0, 0} }; c = getopt_long (argc, argv, "abc:d:0123456789", long_options, &option_index); if (c == -1) break; switch (c) { case 0: printf ("option %s", long_options[option_index].name); if (optarg) printf (" with arg %s", optarg); printf ("\n"); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (digit_optind != 0 && digit_optind != this_option_optind) printf ("digits occur in two different argv-elements.\n"); digit_optind = this_option_optind; printf ("option %c\n", c); break; case 'a': printf ("option a\n"); break; case 'b': printf ("option b\n"); break; case 'c': printf ("option c with value `%s'\n", optarg); break; case 'd': printf ("option d with value `%s'\n", optarg); break; case '?': break; default: printf ("?? getopt returned character code 0%o ??\n", c); } } if (optind < argc) { printf ("non-option ARGV-elements: "); while (optind < argc) printf ("%s ", argv[optind++]); printf ("\n"); } exit (0); } #endif /* TEST */ matanza-0.13/README0000644000175000017500000004573507263450203014137 0ustar boradminboradminMATANZA - THE SLOGAN-LACKING GAME 1. What is Matanza? 2. Who did Matanza? 3. How can I build and install Matanza? 4. Running Matanza's server 5. Playing Matanza 6. The command line arguments 7. Plans for the future -------------------------------------------------------------------------------- 1. WHAT IS MATANZA? Matanza is a multiplayer game. In it, every player controls a ship cruising in space, aiming to destroy the other players (and, eventually, ships controled by the computer). By the way, it is pronounced MATANGA, not Matanza. Currently, the only way to play is through telnet. That's correct, telnet. Everything is rendered to ASCII art. Wonderful, isn't it? You only need to install Matanza in one Machine and you can then play from whatever machines you want, as long as a telnet client is available on them. We are currently working to fix that, implementing the Matanza Machine Protocol into the server. It will allow clients to connect through a different protocol, to display everything using graphics. We've heard of people interested in creating clients using KDE, OpenGL, Java2D and a few other graphic libraries. Once they are ready, it will be possible to play using any of the different available clients. For the moment, however, the only available option is the telnet client. Don't let that get you down, only very recently we thought about adding other clients, as we are very happy with the currently available. Just give it a try and see for yourself why other clients are just alternatives, not that important. Up until version 0.11, the server only ran on Unix platforms. This version, however, will probably work on any Unix operating system plus a few others. So far, we have tested it and got it to work in the following systems: - BeOS - FreeBSD - GNU/Linux - Solaris - Windows 2000 - Windows 98 - Windows NT The game is free software, distributed under the terms of the GNU GPL License. Please see the file COPYING for more information. Yay, you gotta love free software. :) It should be noted that the game should not be considered complete yet, as there are some issues we still have to fix and there are some features still missing. It should, however, be playable as it is. It should be very addictive too. Well, it tries. Please check for more information on new releases. You don't want to end up running this release for years. No. You want to be riding the wave, the BLEEDING EDGE. And you know it. Finally, if you are in any way interested in Matanza, I invite you to subscribe to Matanza's mailing list. There you will find developers interested on listening of your experience with Matanza and any suggestions you might have. Friendly developers. We don't bite. Or not hard. -------------------------------------------------------------------------------- 2. WHO DID MATANZA? Matanza is being developed by Alejandro Forero Cuervo of the Freaks Unidos . Information and beta testing for the port to BeOS was provided by Andrés Felipe Arguello . No other help, other than simple suggestions such as `make it possible to brake!' has been received. I know you are going to find out lots of bugs and come up with lots of wonderful ideas to improve the game. I know you'll also end up wondering how come I am so clueless as to make this and that the way I did. Well, Luke, you can download CWEB , run your text editor on matanza.w and make all the changes your self, submitting me patches to receive full credits. That's right, CREDITS. -------------------------------------------------------------------------------- 3. HOW CAN I BUILD AND INSTALL MATANZA? This depends on what your platform is. If you are using Windows, you might prefer to obtain the binary distribution. Otherwise, you will need a C/C++ compiler and you are on your own. The official binaries are generated using Microsof's Visual Studio. If this is a binary distribution, it is safe to ignore this section. To compile and install Matanza in UNIX and BeOS, follow the instructions in the boring INSTALL file (hint: Standard GNU autoconf stuff). Matanza needs functionality provided by the following libraries. If you don't have them installed, Matanza will still compile and run but some of its features will not work. libpng: libpng is required if you want Matanza to support PNG images. This is strongly recommended, as the PNG format is the format used in Matanza Universes. You can obtain libpng at: If this library is found in your system, the `configure' script will tell you that the PNG format will be supported, in a message similar to: Supported image formats: PNG. -------------------------------------------------------------------------------- 4. RUNNING MATANZA'S SERVER. You must run Matanza's server before anyone can play. This is as simple as typing `matanza' after it has been successfully built and installed (see previous section). The Matanza executable accepts some (okay, a lot of) command line arguments, use `matanza --help' to see a list of them. -------------------------------------------------------------------------------- 5. PLAYING MATANZA. The first thing you must do is connect to the server. You must connect to the TCP port `7993' (unless you specified a different port when you ran the server) of the host running the server. I won't tell you how to do this, Luke. Umm. Don't look at me like that! Ok, you win. It's probably `telnet localhost 7993'. Once connected, you'll see some nice (c'mon give us some credits) introduction. You must hit (that's ) to go to the game's main screen. At the main screen, you must enter your name. That's right, it can't have more than 8 letters. Oh, and it can not begin with a number. Enter your name and hit a few times. If you are in Windows' stupid telnet client, the widgets there will look awful. No colors or anything. We are going to fix that eventually, but... well, you'll have to learn to live with that for the moment. I'm sure you can, Luke. After all, you could stand it when that stupid kid at school used to beat you, remember? But back to our game, you'll see a ship in the middle of screen. Yes, I said ship. Okay, I know it looks more like fire effects than a ship, but with a couple of practice it's going to look better. You just need to train your self to recognize it. Or you could think of it as a big moth and of the bullets as moth-spit and the goal of this game would be to cover your enemies in your spit. Now, that thing in the middle of the screen is YOUR ship. To control it you can use the following keys: `h' and `l': Make the ship rotate. If you are wondering why I used `h' and `l', get a life (in other words, learn to use Vi). It's a matter of style. Actually, I got so many complaints from lukes like you that I added support for arrow keys. `+' and `-': These allow you to zoom in and out. `j' and `k': Accelerate the ship. Yes, it can move! Yes, at different speeds! Okay, `j' may not work (see --brake and --fly-back). More on that latter. Again, arrows key works as well. ` ' (that's space, dude): Shot. Yay! Bullets! Or (depending on your point of view) Moth-Spit! Sorry, dude, the telnet protocol doesn't support sound so there's no BZZZING when you shot. `b': Shot bullets backwards. Sometimes this doesn't work. More on that in section 6. `m': Do you see two little imperfections on your ship's wings? Those are the MISSILES. You can shot them with `m'. They do a lot more damage than the bullets, but you have only two, so be careful. `n': You can also shot SMALLER missiles. You have ten of these. : If you hit , you'll be able to write a message to send it to all the other players. That's correct, you can use Matanza as a full featured chat and all. You could even have net.sex using it, but don't even get me started on the subject. `z': Shows you stats about the game. `c': Removes the last message from the list of messages. `C': Cleans the list of messages. `s': Swaps the position of the list of messages. `p': Pauses the game. `v': Toggles whether or not you see the messages. Sometimes you'll want to disable them. `i': Make your ship invisible! But beware, you may only make it invisible for a short period of time, after that it becomes visible again and you can't become invisible anymore. `q': Quit the game. Okay, those are all the commands. For now. I know, it's kinda pointless to play alone. You'll need to turn your computer off, go outside and make some friends first. Try, it's not that hard. Umm. Eventually, Matanza will support computer-controled ships so if you find it way too hard to make some friends to play Matanza with them, you might modify the code and add this. Don't forget to send me a patch. If you look at the border of your screen, you'll notice some characters and perhaps some asterisks and dots and stuff. Can't see them? Get some other players in the game. Still can't see them? Umm. Turn your monitor on. There you go. Yes, those! (If you still can't see them, see the `--no-radar' option in the next section.) Each character corresponds to another player in the game. If you point your ship in the direction of the character (or asterisk), you will reach one of the player's whose name begins with that character. If the player is too far away, Matanza will draw the character in lowercase. As it gets closer, it will use uppercase. Now, if you see an asterisk, it means the player is way to close so you must get your weapons ready to give the bastard a lesson. Oh, two final words. Please don't miss your classes playing Matanza as much as we did programming it. And remember, it's pronounced MATANGA. Learn how to say it or the gods will punish you. -------------------------------------------------------------------------------- 6. THE COMMAND LINE ARGUMENTS. So you think it's very stupid to allow players to shot backwards? Would you like to increase the number of lives each player has? How about zooming out and making each ship smaller? What about making teams and having each player select a given team when joining the game? Is the world too big or too small? Do you want to get rid of the asteriods or perhaps add a few more? Allow the ships to fly faster? Let them fly backwards? It is all possible, using command line arguments when you run the server. The following is a list of important command line arguments; this was last updated for version 0.12, though some are still missing. --help This shows the list of command line arguments and exits. --version Use this to know the version of the server. --max-players=NUM If you want to make it so the server will allow at most NUM players to enter the world at any given moment, use this option. --bold This instructs the server to use bold characters when rendering images to ASCII art. It improves the quality of the rendering (as of version 0.9 it still has some bugs). --imgwidth=NUM This changes the default image width (for the zoom). The default is 320. --health=NUM Use this option to set the maximum damage a ship can take before it is destroyed. It defaults to 1000. --mapsize-x=NUM --mapsize-y=NUM These options allow you to change the map size. If you make it smaller, players will come across each other more often. On the other hand, if you plan to have a lot of players, you might want to increase the size. The default is 1200 x 1000. --lives=NUM With this option you can change the number of lives each player (or team: see --no-share) gets at startup. --angles=NUM During its initialization, Matanza calculates rotations for all its images (ships, missiles, asteroids, etc.). It uses 64 different angles by default. You may change this number to increase its quality or decrease its memory consumption. --no-chat If you use this option, you will disallow the chat feature. The only reason I can think why someone would want to do that would be to keep newbies from entering the chat buffer and becoming unable to control their ships. Or perhaps to make some team games more exciting by preventing the players to exchange information (though I know it would be very easy to cheat). --team=STR If you want to play in teams mode, you will use this option once for every team, specifing its name. Before joining the game, all players must select the team they will play in. --password[=STR] You can instruct the server to only accept players who know the password. This might be good for some tournaments. --teams-safe This option is only meaningful in teams mode. By default, bullets from a given player hurt everyone, not only players from the other teams. This option changes that behaviour and makes it so bullets from a given player won't hurt players in the same team. --no-share This option is only meaningful in teams mode. By default, all the teams have a pool of lives; when a player dies, he comes back to play and the team has one life less. When this option is specified, the lives are no longer shared so each player has its own pool of lives. --ang-speed-max=NUM Maximum angular speed for ships (try 0) --fly-back If this option is specified, players will be acelerate backwards. --brake Players will be able to brake using `j' (or the down arrow). --air Ships' speed depend on their direction. --speed-max=NUM Set the maximum speed for the ships to NUM. A value of 0 makes this unlimited. --asteroids=NUM With this option you can specify how many asteroids you want at a given moment. If you use `0', you will disable this feature and the memory requirements will decrease. --limits Give the world limits; make it end --no-radar When enemy is away, don't show the direction --invisible=NUM Allow players to become invisible for NUM rounds --ppc=NUM PPC stands for Players Per Connection. With this option, you will be able to set the number of ships each connection will have. For the moment, the only supported values are 1 and 2. The keyboard bindings change and those for a value of 2 are not yet documented. --bg=PATH PATH should be the path to a JPEG file. Matanza will load the information in the file and use it as the background, rather than showing the dots. This will only work if libjpeg was installed when you compiled Matanza. --mapsize-img This option will be ignored unless `--bg' is also used. It tells Matanza to set the map's size to be the width and height of the background image. When used, the options `-x' and `-y' are ignored. --ship-img=FILE Through this option you can specify a file name for Matanza to load the images for the ships from it. The format for the file is very simple, consult ship.txt for more details. -------------------------------------------------------------------------------- 7. PLANS FOR THE FUTURE The following is a list of all the changes we would like to implement for future releases: Proxies: Using telnet as the protocol for Matanza uses a lot of bandwidth. To solve this problem, we are designing a new protocol, MMP. Once it's ready, we will be able to use proxies for connections. For example, lets say Machine A and Machine B are only connected through a slow modem connection. Player A, the owner of Machine A, runs the Matanza server passing it command line arguments to have it listen on a given port using MMP. Player B, stuck in Machine B, runs the server telling it to act as a proxy to the world kept in Machine A. Then both players connect to the servers running on their own machine. Termcap: We should use termcap rather than have the special control sequences hardcoded. Aritificial Intelligence Make it possible to have computer-controled ships. Colors: Every now and then someone comes and suggest using colors. I am not so sure about it. The problems this might have is that for every character you must use only one color while we are drawing exactly four pixels. This would force us to give the same color to all of those pixels. I'm not very happy about that. But yes, as long as they are disabled by default, having this option can't hurt. Collisions: When asteroids collide (and when asteroids and players collide), the way their speeds are modified is very silly. I should get off my lazy ass and come up with another algorithm. And also, have something happen when playing in air mode (--air). Mods: Make it possible to make mods: sets of files that modify the way Matanza behaves. It should be possible, for example, to make a mod `Racer', one where the players can't damage each other, they are just set on a given track (crashing against the walls of the track) and their goal is to be the fastest. Or a mod `RacerDead', a mod like `Racer' where players can shot and kill each other as well. Or a mod `Labyrinth', where the players are stuck in a labyrinth and must destroy each other. Or a mod `CaptureTheFlag', where each team is supposed to steal the other team's flag. Or a mod `DestroyBase', where each team is supposed to destroy the other team's big ship (base). Or a mod ... Multiple Universes: Make it possible for one instance of the server to handle many different universes. Keyboard Bindings: Make it possible to modify the keyboard bindings. Not globally but per-player. Gasoline: Given a command-line argument, have the players run out of gas. There should be some way for them to refill their ships (such as staying over the gas machine). Fix bugs with certain telnet clients: I -think- the telnet-server code has its bugs (please, please, please report them... I can't fix them if I can't find them). It won't work with certain telnet clients. That should be fixed. -------------------------------------------------------------------------------- matanza-0.13/xmltok_ns.c0000644000175000017500000000456307254522236015441 0ustar boradminboradminconst ENCODING *NS(XmlGetUtf8InternalEncoding)(void) { return &ns(internal_utf8_encoding).enc; } const ENCODING *NS(XmlGetUtf16InternalEncoding)(void) { #if XML_BYTE_ORDER == 12 return &ns(internal_little2_encoding).enc; #elif XML_BYTE_ORDER == 21 return &ns(internal_big2_encoding).enc; #else const short n = 1; return *(const char *)&n ? &ns(internal_little2_encoding).enc : &ns(internal_big2_encoding).enc; #endif } static const ENCODING *NS(encodings)[] = { &ns(latin1_encoding).enc, &ns(ascii_encoding).enc, &ns(utf8_encoding).enc, &ns(big2_encoding).enc, &ns(big2_encoding).enc, &ns(little2_encoding).enc, &ns(utf8_encoding).enc /* NO_ENC */ }; static int NS(initScanProlog)(const ENCODING *enc, const char *ptr, const char *end, const char **nextTokPtr) { return initScan(NS(encodings), (const INIT_ENCODING *)enc, XML_PROLOG_STATE, ptr, end, nextTokPtr); } static int NS(initScanContent)(const ENCODING *enc, const char *ptr, const char *end, const char **nextTokPtr) { return initScan(NS(encodings), (const INIT_ENCODING *)enc, XML_CONTENT_STATE, ptr, end, nextTokPtr); } int NS(XmlInitEncoding)(INIT_ENCODING *p, const ENCODING **encPtr, const char *name) { int i = getEncodingIndex(name); if (i == UNKNOWN_ENC) return 0; SET_INIT_ENC_INDEX(p, i); p->initEnc.scanners[XML_PROLOG_STATE] = NS(initScanProlog); p->initEnc.scanners[XML_CONTENT_STATE] = NS(initScanContent); p->initEnc.updatePosition = initUpdatePosition; p->encPtr = encPtr; *encPtr = &(p->initEnc); return 1; } static const ENCODING *NS(findEncoding)(const ENCODING *enc, const char *ptr, const char *end) { #define ENCODING_MAX 128 char buf[ENCODING_MAX]; char *p = buf; int i; XmlUtf8Convert(enc, &ptr, end, &p, p + ENCODING_MAX - 1); if (ptr != end) return 0; *p = 0; if (streqci(buf, KW_UTF_16) && enc->minBytesPerChar == 2) return enc; i = getEncodingIndex(buf); if (i == UNKNOWN_ENC) return 0; return NS(encodings)[i]; } int NS(XmlParseXmlDecl)(int isGeneralTextEntity, const ENCODING *enc, const char *ptr, const char *end, const char **badPtr, const char **versionPtr, const char **encodingName, const ENCODING **encoding, int *standalone) { return doParseXmlDecl(NS(findEncoding), isGeneralTextEntity, enc, ptr, end, badPtr, versionPtr, encodingName, encoding, standalone); } matanza-0.13/asciitab.h0000644000175000017500000000334107254453527015206 0ustar boradminboradmin/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd See the file copying.txt for copying permission. */ /* 0x00 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, /* 0x04 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, /* 0x08 */ BT_NONXML, BT_S, BT_LF, BT_NONXML, /* 0x0C */ BT_NONXML, BT_CR, BT_NONXML, BT_NONXML, /* 0x10 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, /* 0x14 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, /* 0x18 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, /* 0x1C */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, /* 0x20 */ BT_S, BT_EXCL, BT_QUOT, BT_NUM, /* 0x24 */ BT_OTHER, BT_PERCNT, BT_AMP, BT_APOS, /* 0x28 */ BT_LPAR, BT_RPAR, BT_AST, BT_PLUS, /* 0x2C */ BT_COMMA, BT_MINUS, BT_NAME, BT_SOL, /* 0x30 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT, /* 0x34 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT, /* 0x38 */ BT_DIGIT, BT_DIGIT, BT_COLON, BT_SEMI, /* 0x3C */ BT_LT, BT_EQUALS, BT_GT, BT_QUEST, /* 0x40 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX, /* 0x44 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT, /* 0x48 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0x4C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0x50 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0x54 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0x58 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_LSQB, /* 0x5C */ BT_OTHER, BT_RSQB, BT_OTHER, BT_NMSTRT, /* 0x60 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX, /* 0x64 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT, /* 0x68 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0x6C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0x70 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0x74 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0x78 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER, /* 0x7C */ BT_VERBAR, BT_OTHER, BT_OTHER, BT_OTHER, matanza-0.13/xmlrole.c0000644000175000017500000006752307254522236015112 0ustar boradminboradmin/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd See the file copying.txt for copying permission. */ #include "xmldef.h" #include "xmlrole.h" #include "ascii.h" /* Doesn't check: that ,| are not mixed in a model group content of literals */ static const char KW_ANY[] = { ASCII_A, ASCII_N, ASCII_Y, '\0' }; static const char KW_ATTLIST[] = { ASCII_A, ASCII_T, ASCII_T, ASCII_L, ASCII_I, ASCII_S, ASCII_T, '\0' }; static const char KW_CDATA[] = { ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' }; static const char KW_DOCTYPE[] = { ASCII_D, ASCII_O, ASCII_C, ASCII_T, ASCII_Y, ASCII_P, ASCII_E, '\0' }; static const char KW_ELEMENT[] = { ASCII_E, ASCII_L, ASCII_E, ASCII_M, ASCII_E, ASCII_N, ASCII_T, '\0' }; static const char KW_EMPTY[] = { ASCII_E, ASCII_M, ASCII_P, ASCII_T, ASCII_Y, '\0' }; static const char KW_ENTITIES[] = { ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T, ASCII_I, ASCII_E, ASCII_S, '\0' }; static const char KW_ENTITY[] = { ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T, ASCII_Y, '\0' }; static const char KW_FIXED[] = { ASCII_F, ASCII_I, ASCII_X, ASCII_E, ASCII_D, '\0' }; static const char KW_ID[] = { ASCII_I, ASCII_D, '\0' }; static const char KW_IDREF[] = { ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, '\0' }; static const char KW_IDREFS[] = { ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, ASCII_S, '\0' }; static const char KW_IGNORE[] = { ASCII_I, ASCII_G, ASCII_N, ASCII_O, ASCII_R, ASCII_E, '\0' }; static const char KW_IMPLIED[] = { ASCII_I, ASCII_M, ASCII_P, ASCII_L, ASCII_I, ASCII_E, ASCII_D, '\0' }; static const char KW_INCLUDE[] = { ASCII_I, ASCII_N, ASCII_C, ASCII_L, ASCII_U, ASCII_D, ASCII_E, '\0' }; static const char KW_NDATA[] = { ASCII_N, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' }; static const char KW_NMTOKEN[] = { ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K, ASCII_E, ASCII_N, '\0' }; static const char KW_NMTOKENS[] = { ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K, ASCII_E, ASCII_N, ASCII_S, '\0' }; static const char KW_NOTATION[] = { ASCII_N, ASCII_O, ASCII_T, ASCII_A, ASCII_T, ASCII_I, ASCII_O, ASCII_N, '\0' }; static const char KW_PCDATA[] = { ASCII_P, ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' }; static const char KW_PUBLIC[] = { ASCII_P, ASCII_U, ASCII_B, ASCII_L, ASCII_I, ASCII_C, '\0' }; static const char KW_REQUIRED[] = { ASCII_R, ASCII_E, ASCII_Q, ASCII_U, ASCII_I, ASCII_R, ASCII_E, ASCII_D, '\0' }; static const char KW_SYSTEM[] = { ASCII_S, ASCII_Y, ASCII_S, ASCII_T, ASCII_E, ASCII_M, '\0' }; #ifndef MIN_BYTES_PER_CHAR #define MIN_BYTES_PER_CHAR(enc) ((enc)->minBytesPerChar) #endif #ifdef XML_DTD #define setTopLevel(state) \ ((state)->handler = ((state)->documentEntity \ ? internalSubset \ : externalSubset1)) #else /* not XML_DTD */ #define setTopLevel(state) ((state)->handler = internalSubset) #endif /* not XML_DTD */ typedef int PROLOG_HANDLER(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc); static PROLOG_HANDLER prolog0, prolog1, prolog2, doctype0, doctype1, doctype2, doctype3, doctype4, doctype5, internalSubset, entity0, entity1, entity2, entity3, entity4, entity5, entity6, entity7, entity8, entity9, notation0, notation1, notation2, notation3, notation4, attlist0, attlist1, attlist2, attlist3, attlist4, attlist5, attlist6, attlist7, attlist8, attlist9, element0, element1, element2, element3, element4, element5, element6, element7, #ifdef XML_DTD externalSubset0, externalSubset1, condSect0, condSect1, condSect2, #endif /* XML_DTD */ declClose, error; static int common(PROLOG_STATE *state, int tok); static int prolog0(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: state->handler = prolog1; return XML_ROLE_NONE; case XML_TOK_XML_DECL: state->handler = prolog1; return XML_ROLE_XML_DECL; case XML_TOK_PI: state->handler = prolog1; return XML_ROLE_NONE; case XML_TOK_COMMENT: state->handler = prolog1; case XML_TOK_BOM: return XML_ROLE_NONE; case XML_TOK_DECL_OPEN: if (!XmlNameMatchesAscii(enc, ptr + 2 * MIN_BYTES_PER_CHAR(enc), end, KW_DOCTYPE)) break; state->handler = doctype0; return XML_ROLE_NONE; case XML_TOK_INSTANCE_START: state->handler = error; return XML_ROLE_INSTANCE_START; } return common(state, tok); } static int prolog1(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_PI: case XML_TOK_COMMENT: case XML_TOK_BOM: return XML_ROLE_NONE; case XML_TOK_DECL_OPEN: if (!XmlNameMatchesAscii(enc, ptr + 2 * MIN_BYTES_PER_CHAR(enc), end, KW_DOCTYPE)) break; state->handler = doctype0; return XML_ROLE_NONE; case XML_TOK_INSTANCE_START: state->handler = error; return XML_ROLE_INSTANCE_START; } return common(state, tok); } static int prolog2(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_PI: case XML_TOK_COMMENT: return XML_ROLE_NONE; case XML_TOK_INSTANCE_START: state->handler = error; return XML_ROLE_INSTANCE_START; } return common(state, tok); } static int doctype0(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_NAME: case XML_TOK_PREFIXED_NAME: state->handler = doctype1; return XML_ROLE_DOCTYPE_NAME; } return common(state, tok); } static int doctype1(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_OPEN_BRACKET: state->handler = internalSubset; return XML_ROLE_NONE; case XML_TOK_DECL_CLOSE: state->handler = prolog2; return XML_ROLE_DOCTYPE_CLOSE; case XML_TOK_NAME: if (XmlNameMatchesAscii(enc, ptr, end, KW_SYSTEM)) { state->handler = doctype3; return XML_ROLE_NONE; } if (XmlNameMatchesAscii(enc, ptr, end, KW_PUBLIC)) { state->handler = doctype2; return XML_ROLE_NONE; } break; } return common(state, tok); } static int doctype2(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_LITERAL: state->handler = doctype3; return XML_ROLE_DOCTYPE_PUBLIC_ID; } return common(state, tok); } static int doctype3(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_LITERAL: state->handler = doctype4; return XML_ROLE_DOCTYPE_SYSTEM_ID; } return common(state, tok); } static int doctype4(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_OPEN_BRACKET: state->handler = internalSubset; return XML_ROLE_NONE; case XML_TOK_DECL_CLOSE: state->handler = prolog2; return XML_ROLE_DOCTYPE_CLOSE; } return common(state, tok); } static int doctype5(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_DECL_CLOSE: state->handler = prolog2; return XML_ROLE_DOCTYPE_CLOSE; } return common(state, tok); } static int internalSubset(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_DECL_OPEN: if (XmlNameMatchesAscii(enc, ptr + 2 * MIN_BYTES_PER_CHAR(enc), end, KW_ENTITY)) { state->handler = entity0; return XML_ROLE_NONE; } if (XmlNameMatchesAscii(enc, ptr + 2 * MIN_BYTES_PER_CHAR(enc), end, KW_ATTLIST)) { state->handler = attlist0; return XML_ROLE_NONE; } if (XmlNameMatchesAscii(enc, ptr + 2 * MIN_BYTES_PER_CHAR(enc), end, KW_ELEMENT)) { state->handler = element0; return XML_ROLE_NONE; } if (XmlNameMatchesAscii(enc, ptr + 2 * MIN_BYTES_PER_CHAR(enc), end, KW_NOTATION)) { state->handler = notation0; return XML_ROLE_NONE; } break; case XML_TOK_PI: case XML_TOK_COMMENT: return XML_ROLE_NONE; case XML_TOK_PARAM_ENTITY_REF: return XML_ROLE_PARAM_ENTITY_REF; case XML_TOK_CLOSE_BRACKET: state->handler = doctype5; return XML_ROLE_NONE; } return common(state, tok); } #ifdef XML_DTD static int externalSubset0(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { state->handler = externalSubset1; if (tok == XML_TOK_XML_DECL) return XML_ROLE_TEXT_DECL; return externalSubset1(state, tok, ptr, end, enc); } static int externalSubset1(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_COND_SECT_OPEN: state->handler = condSect0; return XML_ROLE_NONE; case XML_TOK_COND_SECT_CLOSE: if (state->includeLevel == 0) break; state->includeLevel -= 1; return XML_ROLE_NONE; case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_CLOSE_BRACKET: break; case XML_TOK_NONE: if (state->includeLevel) break; return XML_ROLE_NONE; default: return internalSubset(state, tok, ptr, end, enc); } return common(state, tok); } #endif /* XML_DTD */ static int entity0(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_PERCENT: state->handler = entity1; return XML_ROLE_NONE; case XML_TOK_NAME: state->handler = entity2; return XML_ROLE_GENERAL_ENTITY_NAME; } return common(state, tok); } static int entity1(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_NAME: state->handler = entity7; return XML_ROLE_PARAM_ENTITY_NAME; } return common(state, tok); } static int entity2(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_NAME: if (XmlNameMatchesAscii(enc, ptr, end, KW_SYSTEM)) { state->handler = entity4; return XML_ROLE_NONE; } if (XmlNameMatchesAscii(enc, ptr, end, KW_PUBLIC)) { state->handler = entity3; return XML_ROLE_NONE; } break; case XML_TOK_LITERAL: state->handler = declClose; return XML_ROLE_ENTITY_VALUE; } return common(state, tok); } static int entity3(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_LITERAL: state->handler = entity4; return XML_ROLE_ENTITY_PUBLIC_ID; } return common(state, tok); } static int entity4(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_LITERAL: state->handler = entity5; return XML_ROLE_ENTITY_SYSTEM_ID; } return common(state, tok); } static int entity5(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_DECL_CLOSE: setTopLevel(state); return XML_ROLE_EXTERNAL_GENERAL_ENTITY_NO_NOTATION; case XML_TOK_NAME: if (XmlNameMatchesAscii(enc, ptr, end, KW_NDATA)) { state->handler = entity6; return XML_ROLE_NONE; } break; } return common(state, tok); } static int entity6(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_NAME: state->handler = declClose; return XML_ROLE_ENTITY_NOTATION_NAME; } return common(state, tok); } static int entity7(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_NAME: if (XmlNameMatchesAscii(enc, ptr, end, KW_SYSTEM)) { state->handler = entity9; return XML_ROLE_NONE; } if (XmlNameMatchesAscii(enc, ptr, end, KW_PUBLIC)) { state->handler = entity8; return XML_ROLE_NONE; } break; case XML_TOK_LITERAL: state->handler = declClose; return XML_ROLE_ENTITY_VALUE; } return common(state, tok); } static int entity8(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_LITERAL: state->handler = entity9; return XML_ROLE_ENTITY_PUBLIC_ID; } return common(state, tok); } static int entity9(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_LITERAL: state->handler = declClose; return XML_ROLE_ENTITY_SYSTEM_ID; } return common(state, tok); } static int notation0(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_NAME: state->handler = notation1; return XML_ROLE_NOTATION_NAME; } return common(state, tok); } static int notation1(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_NAME: if (XmlNameMatchesAscii(enc, ptr, end, KW_SYSTEM)) { state->handler = notation3; return XML_ROLE_NONE; } if (XmlNameMatchesAscii(enc, ptr, end, KW_PUBLIC)) { state->handler = notation2; return XML_ROLE_NONE; } break; } return common(state, tok); } static int notation2(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_LITERAL: state->handler = notation4; return XML_ROLE_NOTATION_PUBLIC_ID; } return common(state, tok); } static int notation3(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_LITERAL: state->handler = declClose; return XML_ROLE_NOTATION_SYSTEM_ID; } return common(state, tok); } static int notation4(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_LITERAL: state->handler = declClose; return XML_ROLE_NOTATION_SYSTEM_ID; case XML_TOK_DECL_CLOSE: setTopLevel(state); return XML_ROLE_NOTATION_NO_SYSTEM_ID; } return common(state, tok); } static int attlist0(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_NAME: case XML_TOK_PREFIXED_NAME: state->handler = attlist1; return XML_ROLE_ATTLIST_ELEMENT_NAME; } return common(state, tok); } static int attlist1(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_DECL_CLOSE: setTopLevel(state); return XML_ROLE_NONE; case XML_TOK_NAME: case XML_TOK_PREFIXED_NAME: state->handler = attlist2; return XML_ROLE_ATTRIBUTE_NAME; } return common(state, tok); } static int attlist2(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_NAME: { static const char *types[] = { KW_CDATA, KW_ID, KW_IDREF, KW_IDREFS, KW_ENTITY, KW_ENTITIES, KW_NMTOKEN, KW_NMTOKENS, }; int i; for (i = 0; i < (int)(sizeof(types)/sizeof(types[0])); i++) if (XmlNameMatchesAscii(enc, ptr, end, types[i])) { state->handler = attlist8; return XML_ROLE_ATTRIBUTE_TYPE_CDATA + i; } } if (XmlNameMatchesAscii(enc, ptr, end, KW_NOTATION)) { state->handler = attlist5; return XML_ROLE_NONE; } break; case XML_TOK_OPEN_PAREN: state->handler = attlist3; return XML_ROLE_NONE; } return common(state, tok); } static int attlist3(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_NMTOKEN: case XML_TOK_NAME: case XML_TOK_PREFIXED_NAME: state->handler = attlist4; return XML_ROLE_ATTRIBUTE_ENUM_VALUE; } return common(state, tok); } static int attlist4(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_CLOSE_PAREN: state->handler = attlist8; return XML_ROLE_NONE; case XML_TOK_OR: state->handler = attlist3; return XML_ROLE_NONE; } return common(state, tok); } static int attlist5(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_OPEN_PAREN: state->handler = attlist6; return XML_ROLE_NONE; } return common(state, tok); } static int attlist6(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_NAME: state->handler = attlist7; return XML_ROLE_ATTRIBUTE_NOTATION_VALUE; } return common(state, tok); } static int attlist7(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_CLOSE_PAREN: state->handler = attlist8; return XML_ROLE_NONE; case XML_TOK_OR: state->handler = attlist6; return XML_ROLE_NONE; } return common(state, tok); } /* default value */ static int attlist8(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_POUND_NAME: if (XmlNameMatchesAscii(enc, ptr + MIN_BYTES_PER_CHAR(enc), end, KW_IMPLIED)) { state->handler = attlist1; return XML_ROLE_IMPLIED_ATTRIBUTE_VALUE; } if (XmlNameMatchesAscii(enc, ptr + MIN_BYTES_PER_CHAR(enc), end, KW_REQUIRED)) { state->handler = attlist1; return XML_ROLE_REQUIRED_ATTRIBUTE_VALUE; } if (XmlNameMatchesAscii(enc, ptr + MIN_BYTES_PER_CHAR(enc), end, KW_FIXED)) { state->handler = attlist9; return XML_ROLE_NONE; } break; case XML_TOK_LITERAL: state->handler = attlist1; return XML_ROLE_DEFAULT_ATTRIBUTE_VALUE; } return common(state, tok); } static int attlist9(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_LITERAL: state->handler = attlist1; return XML_ROLE_FIXED_ATTRIBUTE_VALUE; } return common(state, tok); } static int element0(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_NAME: case XML_TOK_PREFIXED_NAME: state->handler = element1; return XML_ROLE_ELEMENT_NAME; } return common(state, tok); } static int element1(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_NAME: if (XmlNameMatchesAscii(enc, ptr, end, KW_EMPTY)) { state->handler = declClose; return XML_ROLE_CONTENT_EMPTY; } if (XmlNameMatchesAscii(enc, ptr, end, KW_ANY)) { state->handler = declClose; return XML_ROLE_CONTENT_ANY; } break; case XML_TOK_OPEN_PAREN: state->handler = element2; state->level = 1; return XML_ROLE_GROUP_OPEN; } return common(state, tok); } static int element2(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_POUND_NAME: if (XmlNameMatchesAscii(enc, ptr + MIN_BYTES_PER_CHAR(enc), end, KW_PCDATA)) { state->handler = element3; return XML_ROLE_CONTENT_PCDATA; } break; case XML_TOK_OPEN_PAREN: state->level = 2; state->handler = element6; return XML_ROLE_GROUP_OPEN; case XML_TOK_NAME: case XML_TOK_PREFIXED_NAME: state->handler = element7; return XML_ROLE_CONTENT_ELEMENT; case XML_TOK_NAME_QUESTION: state->handler = element7; return XML_ROLE_CONTENT_ELEMENT_OPT; case XML_TOK_NAME_ASTERISK: state->handler = element7; return XML_ROLE_CONTENT_ELEMENT_REP; case XML_TOK_NAME_PLUS: state->handler = element7; return XML_ROLE_CONTENT_ELEMENT_PLUS; } return common(state, tok); } static int element3(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_CLOSE_PAREN: case XML_TOK_CLOSE_PAREN_ASTERISK: state->handler = declClose; return XML_ROLE_GROUP_CLOSE_REP; case XML_TOK_OR: state->handler = element4; return XML_ROLE_NONE; } return common(state, tok); } static int element4(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_NAME: case XML_TOK_PREFIXED_NAME: state->handler = element5; return XML_ROLE_CONTENT_ELEMENT; } return common(state, tok); } static int element5(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_CLOSE_PAREN_ASTERISK: state->handler = declClose; return XML_ROLE_GROUP_CLOSE_REP; case XML_TOK_OR: state->handler = element4; return XML_ROLE_NONE; } return common(state, tok); } static int element6(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_OPEN_PAREN: state->level += 1; return XML_ROLE_GROUP_OPEN; case XML_TOK_NAME: case XML_TOK_PREFIXED_NAME: state->handler = element7; return XML_ROLE_CONTENT_ELEMENT; case XML_TOK_NAME_QUESTION: state->handler = element7; return XML_ROLE_CONTENT_ELEMENT_OPT; case XML_TOK_NAME_ASTERISK: state->handler = element7; return XML_ROLE_CONTENT_ELEMENT_REP; case XML_TOK_NAME_PLUS: state->handler = element7; return XML_ROLE_CONTENT_ELEMENT_PLUS; } return common(state, tok); } static int element7(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_CLOSE_PAREN: state->level -= 1; if (state->level == 0) state->handler = declClose; return XML_ROLE_GROUP_CLOSE; case XML_TOK_CLOSE_PAREN_ASTERISK: state->level -= 1; if (state->level == 0) state->handler = declClose; return XML_ROLE_GROUP_CLOSE_REP; case XML_TOK_CLOSE_PAREN_QUESTION: state->level -= 1; if (state->level == 0) state->handler = declClose; return XML_ROLE_GROUP_CLOSE_OPT; case XML_TOK_CLOSE_PAREN_PLUS: state->level -= 1; if (state->level == 0) state->handler = declClose; return XML_ROLE_GROUP_CLOSE_PLUS; case XML_TOK_COMMA: state->handler = element6; return XML_ROLE_GROUP_SEQUENCE; case XML_TOK_OR: state->handler = element6; return XML_ROLE_GROUP_CHOICE; } return common(state, tok); } #ifdef XML_DTD static int condSect0(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_NAME: if (XmlNameMatchesAscii(enc, ptr, end, KW_INCLUDE)) { state->handler = condSect1; return XML_ROLE_NONE; } if (XmlNameMatchesAscii(enc, ptr, end, KW_IGNORE)) { state->handler = condSect2; return XML_ROLE_NONE; } break; } return common(state, tok); } static int condSect1(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_OPEN_BRACKET: state->handler = externalSubset1; state->includeLevel += 1; return XML_ROLE_NONE; } return common(state, tok); } static int condSect2(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_OPEN_BRACKET: state->handler = externalSubset1; return XML_ROLE_IGNORE_SECT; } return common(state, tok); } #endif /* XML_DTD */ static int declClose(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_DECL_CLOSE: setTopLevel(state); return XML_ROLE_NONE; } return common(state, tok); } #if 0 static int ignore(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_DECL_CLOSE: state->handler = internalSubset; return 0; default: return XML_ROLE_NONE; } return common(state, tok); } #endif static int error(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { return XML_ROLE_NONE; } static int common(PROLOG_STATE *state, int tok) { #ifdef XML_DTD if (!state->documentEntity && tok == XML_TOK_PARAM_ENTITY_REF) return XML_ROLE_INNER_PARAM_ENTITY_REF; #endif state->handler = error; return XML_ROLE_ERROR; } void XmlPrologStateInit(PROLOG_STATE *state) { state->handler = prolog0; #ifdef XML_DTD state->documentEntity = 1; state->includeLevel = 0; #endif /* XML_DTD */ } #ifdef XML_DTD void XmlPrologStateInitExternalEntity(PROLOG_STATE *state) { state->handler = externalSubset0; state->documentEntity = 0; state->includeLevel = 0; } #endif /* XML_DTD */ matanza-0.13/configure0000755000175000017500000022646107263463410015167 0ustar boradminboradmin#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated automatically using autoconf version 2.13 # Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. # Defaults: ac_help= ac_default_prefix=/usr/local # Any additions from configure.in: ac_help="$ac_help --enable-profile turn on profiling [default=no]" ac_help="$ac_help --enable-debug turn on debugging [default=no]" ac_help="$ac_help --enable-efence Link against efence [default=no]" # Initialize some variables set by options. # The variables have the same names as the options, with # dashes changed to underlines. build=NONE cache_file=./config.cache exec_prefix=NONE host=NONE no_create= nonopt=NONE no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= target=NONE verbose= x_includes=NONE x_libraries=NONE bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datadir='${prefix}/share' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' libdir='${exec_prefix}/lib' includedir='${prefix}/include' oldincludedir='/usr/include' infodir='${prefix}/info' mandir='${prefix}/man' # Initialize some other variables. subdirs= MFLAGS= MAKEFLAGS= SHELL=${CONFIG_SHELL-/bin/sh} # Maximum number of lines to put in a shell here document. ac_max_here_lines=12 ac_prev= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval "$ac_prev=\$ac_option" ac_prev= continue fi case "$ac_option" in -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; *) ac_optarg= ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case "$ac_option" in -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir="$ac_optarg" ;; -build | --build | --buil | --bui | --bu) ac_prev=build ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build="$ac_optarg" ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file="$ac_optarg" ;; -datadir | --datadir | --datadi | --datad | --data | --dat | --da) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ | --da=*) datadir="$ac_optarg" ;; -disable-* | --disable-*) ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` # Reject names that are not valid shell variable names. if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } fi ac_feature=`echo $ac_feature| sed 's/-/_/g'` eval "enable_${ac_feature}=no" ;; -enable-* | --enable-*) ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` # Reject names that are not valid shell variable names. if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } fi ac_feature=`echo $ac_feature| sed 's/-/_/g'` case "$ac_option" in *=*) ;; *) ac_optarg=yes ;; esac eval "enable_${ac_feature}='$ac_optarg'" ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix="$ac_optarg" ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he) # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat << EOF Usage: configure [options] [host] Options: [defaults in brackets after descriptions] Configuration: --cache-file=FILE cache test results in FILE --help print this message --no-create do not create output files --quiet, --silent do not print \`checking...' messages --version print the version of autoconf that created configure Directory and file names: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [same as prefix] --bindir=DIR user executables in DIR [EPREFIX/bin] --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] --libexecdir=DIR program executables in DIR [EPREFIX/libexec] --datadir=DIR read-only architecture-independent data in DIR [PREFIX/share] --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data in DIR [PREFIX/com] --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] --libdir=DIR object code libraries in DIR [EPREFIX/lib] --includedir=DIR C header files in DIR [PREFIX/include] --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] --infodir=DIR info documentation in DIR [PREFIX/info] --mandir=DIR man documentation in DIR [PREFIX/man] --srcdir=DIR find the sources in DIR [configure dir or ..] --program-prefix=PREFIX prepend PREFIX to installed program names --program-suffix=SUFFIX append SUFFIX to installed program names --program-transform-name=PROGRAM run sed PROGRAM on installed program names EOF cat << EOF Host type: --build=BUILD configure for building on BUILD [BUILD=HOST] --host=HOST configure for HOST [guessed] --target=TARGET configure for TARGET [TARGET=HOST] Features and packages: --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --x-includes=DIR X include files are in DIR --x-libraries=DIR X library files are in DIR EOF if test -n "$ac_help"; then echo "--enable and --with options recognized:$ac_help" fi exit 0 ;; -host | --host | --hos | --ho) ac_prev=host ;; -host=* | --host=* | --hos=* | --ho=*) host="$ac_optarg" ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir="$ac_optarg" ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir="$ac_optarg" ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir="$ac_optarg" ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir="$ac_optarg" ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst \ | --locals | --local | --loca | --loc | --lo) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* \ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) localstatedir="$ac_optarg" ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir="$ac_optarg" ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir="$ac_optarg" ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix="$ac_optarg" ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix="$ac_optarg" ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix="$ac_optarg" ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name="$ac_optarg" ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir="$ac_optarg" ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir="$ac_optarg" ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site="$ac_optarg" ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir="$ac_optarg" ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir="$ac_optarg" ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target="$ac_optarg" ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers) echo "configure generated by autoconf version 2.13" exit 0 ;; -with-* | --with-*) ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` # Reject names that are not valid shell variable names. if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } fi ac_package=`echo $ac_package| sed 's/-/_/g'` case "$ac_option" in *=*) ;; *) ac_optarg=yes ;; esac eval "with_${ac_package}='$ac_optarg'" ;; -without-* | --without-*) ac_package=`echo $ac_option|sed -e 's/-*without-//'` # Reject names that are not valid shell variable names. if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } fi ac_package=`echo $ac_package| sed 's/-/_/g'` eval "with_${ac_package}=no" ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes="$ac_optarg" ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries="$ac_optarg" ;; -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } ;; *) if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then echo "configure: warning: $ac_option: invalid host type" 1>&2 fi if test "x$nonopt" != xNONE; then { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } fi nonopt="$ac_option" ;; esac done if test -n "$ac_prev"; then { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } fi trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 # File descriptor usage: # 0 standard input # 1 file creation # 2 errors and warnings # 3 some systems may open it to /dev/tty # 4 used on the Kubota Titan # 6 checking for... messages and results # 5 compiler messages saved in config.log if test "$silent" = yes; then exec 6>/dev/null else exec 6>&1 fi exec 5>./config.log echo "\ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. " 1>&5 # Strip out --no-create and --no-recursion so they do not pile up. # Also quote any args containing shell metacharacters. ac_configure_args= for ac_arg do case "$ac_arg" in -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c) ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) ac_configure_args="$ac_configure_args '$ac_arg'" ;; *) ac_configure_args="$ac_configure_args $ac_arg" ;; esac done # NLS nuisances. # Only set these to C if already set. These must not be set unconditionally # because not all systems understand e.g. LANG=C (notably SCO). # Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! # Non-C LC_CTYPE values break the ctype check. if test "${LANG+set}" = set; then LANG=C; export LANG; fi if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -rf conftest* confdefs.h # AIX cpp loses on an empty file, so make sure it contains at least a newline. echo > confdefs.h # A filename unique to this package, relative to the directory that # configure is in, which we can look for to find out if srcdir is correct. ac_unique_file=matanza.w # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then its parent. ac_prog=$0 ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. srcdir=$ac_confdir if test ! -r $srcdir/$ac_unique_file; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r $srcdir/$ac_unique_file; then if test "$ac_srcdir_defaulted" = yes; then { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } else { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } fi fi srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` # Prefer explicitly selected file to automatically selected ones. if test -z "$CONFIG_SITE"; then if test "x$prefix" != xNONE; then CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" else CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" fi fi for ac_site_file in $CONFIG_SITE; do if test -r "$ac_site_file"; then echo "loading site script $ac_site_file" . "$ac_site_file" fi done if test -r "$cache_file"; then echo "loading cache $cache_file" . $cache_file else echo "creating cache $cache_file" > $cache_file fi ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. ac_cpp='$CPP $CPPFLAGS' ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' cross_compiling=$ac_cv_prog_cc_cross ac_exeext= ac_objext=o if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then ac_n= ac_c=' ' ac_t=' ' else ac_n=-n ac_c= ac_t= fi else ac_n= ac_c='\c' ac_t= fi ac_aux_dir= for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do if test -f $ac_dir/install-sh; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f $ac_dir/install.sh; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break fi done if test -z "$ac_aux_dir"; then { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; } fi ac_config_guess=$ac_aux_dir/config.guess ac_config_sub=$ac_aux_dir/config.sub ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # ./install, which can be erroneously created by make from ./install.sh. echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 echo "configure:564: checking for a BSD compatible install" >&5 if test -z "$INSTALL"; then if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":" for ac_dir in $PATH; do # Account for people who put trailing slashes in PATH elements. case "$ac_dir/" in /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do if test -f $ac_dir/$ac_prog; then if test $ac_prog = install && grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : else ac_cv_path_install="$ac_dir/$ac_prog -c" break 2 fi fi done ;; esac done IFS="$ac_save_IFS" fi if test "${ac_cv_path_install+set}" = set; then INSTALL="$ac_cv_path_install" else # As a last resort, use the slow shell script. We don't cache a # path for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the path is relative. INSTALL="$ac_install_sh" fi fi echo "$ac_t""$INSTALL" 1>&6 # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' echo $ac_n "checking whether build environment is sane""... $ac_c" 1>&6 echo "configure:617: checking whether build environment is sane" >&5 # Just in case sleep 1 echo timestamp > conftestfile # Do `set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null` if test "$*" = "X"; then # -L didn't work. set X `ls -t $srcdir/configure conftestfile` fi if test "$*" != "X $srcdir/configure conftestfile" \ && test "$*" != "X conftestfile $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". { echo "configure: error: ls -t appears to fail. Make sure there is not a broken alias in your environment" 1>&2; exit 1; } fi test "$2" = conftestfile ) then # Ok. : else { echo "configure: error: newly created file is older than distributed files! Check your system clock" 1>&2; exit 1; } fi rm -f conftest* echo "$ac_t""yes" 1>&6 if test "$program_transform_name" = s,x,x,; then program_transform_name= else # Double any \ or $. echo might interpret backslashes. cat <<\EOF_SED > conftestsed s,\\,\\\\,g; s,\$,$$,g EOF_SED program_transform_name="`echo $program_transform_name|sed -f conftestsed`" rm -f conftestsed fi test "$program_prefix" != NONE && program_transform_name="s,^,${program_prefix},; $program_transform_name" # Use a double $ so make ignores it. test "$program_suffix" != NONE && program_transform_name="s,\$\$,${program_suffix},; $program_transform_name" # sed with no file args requires a program. test "$program_transform_name" = "" && program_transform_name="s,x,x," echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 echo "configure:674: checking whether ${MAKE-make} sets \${MAKE}" >&5 set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftestmake <<\EOF all: @echo 'ac_maketemp="${MAKE}"' EOF # GNU make sometimes prints "make[1]: Entering...", which would confuse us. eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=` if test -n "$ac_maketemp"; then eval ac_cv_prog_make_${ac_make}_set=yes else eval ac_cv_prog_make_${ac_make}_set=no fi rm -f conftestmake fi if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then echo "$ac_t""yes" 1>&6 SET_MAKE= else echo "$ac_t""no" 1>&6 SET_MAKE="MAKE=${MAKE-make}" fi PACKAGE=matanza VERSION=0.13 if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then { echo "configure: error: source directory already configured; run "make distclean" there first" 1>&2; exit 1; } fi cat >> confdefs.h <> confdefs.h <&6 echo "configure:720: checking for working aclocal" >&5 # Run test in a subshell; some versions of sh will print an error if # an executable is not found, even if stderr is redirected. # Redirect stdin to placate older versions of autoconf. Sigh. if (aclocal --version) < /dev/null > /dev/null 2>&1; then ACLOCAL=aclocal echo "$ac_t""found" 1>&6 else ACLOCAL="$missing_dir/missing aclocal" echo "$ac_t""missing" 1>&6 fi echo $ac_n "checking for working autoconf""... $ac_c" 1>&6 echo "configure:733: checking for working autoconf" >&5 # Run test in a subshell; some versions of sh will print an error if # an executable is not found, even if stderr is redirected. # Redirect stdin to placate older versions of autoconf. Sigh. if (autoconf --version) < /dev/null > /dev/null 2>&1; then AUTOCONF=autoconf echo "$ac_t""found" 1>&6 else AUTOCONF="$missing_dir/missing autoconf" echo "$ac_t""missing" 1>&6 fi echo $ac_n "checking for working automake""... $ac_c" 1>&6 echo "configure:746: checking for working automake" >&5 # Run test in a subshell; some versions of sh will print an error if # an executable is not found, even if stderr is redirected. # Redirect stdin to placate older versions of autoconf. Sigh. if (automake --version) < /dev/null > /dev/null 2>&1; then AUTOMAKE=automake echo "$ac_t""found" 1>&6 else AUTOMAKE="$missing_dir/missing automake" echo "$ac_t""missing" 1>&6 fi echo $ac_n "checking for working autoheader""... $ac_c" 1>&6 echo "configure:759: checking for working autoheader" >&5 # Run test in a subshell; some versions of sh will print an error if # an executable is not found, even if stderr is redirected. # Redirect stdin to placate older versions of autoconf. Sigh. if (autoheader --version) < /dev/null > /dev/null 2>&1; then AUTOHEADER=autoheader echo "$ac_t""found" 1>&6 else AUTOHEADER="$missing_dir/missing autoheader" echo "$ac_t""missing" 1>&6 fi echo $ac_n "checking for working makeinfo""... $ac_c" 1>&6 echo "configure:772: checking for working makeinfo" >&5 # Run test in a subshell; some versions of sh will print an error if # an executable is not found, even if stderr is redirected. # Redirect stdin to placate older versions of autoconf. Sigh. if (makeinfo --version) < /dev/null > /dev/null 2>&1; then MAKEINFO=makeinfo echo "$ac_t""found" 1>&6 else MAKEINFO="$missing_dir/missing makeinfo" echo "$ac_t""missing" 1>&6 fi # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 echo "configure:793: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ac_dummy="$PATH" for ac_dir in $ac_dummy; do test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$ac_word; then ac_cv_prog_CC="gcc" break fi done IFS="$ac_save_ifs" fi fi CC="$ac_cv_prog_CC" if test -n "$CC"; then echo "$ac_t""$CC" 1>&6 else echo "$ac_t""no" 1>&6 fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 echo "configure:823: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ac_prog_rejected=no ac_dummy="$PATH" for ac_dir in $ac_dummy; do test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$ac_word; then if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" break fi done IFS="$ac_save_ifs" if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# -gt 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift set dummy "$ac_dir/$ac_word" "$@" shift ac_cv_prog_CC="$@" fi fi fi fi CC="$ac_cv_prog_CC" if test -n "$CC"; then echo "$ac_t""$CC" 1>&6 else echo "$ac_t""no" 1>&6 fi if test -z "$CC"; then case "`uname -s`" in *win32* | *WIN32*) # Extract the first word of "cl", so it can be a program name with args. set dummy cl; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 echo "configure:874: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ac_dummy="$PATH" for ac_dir in $ac_dummy; do test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$ac_word; then ac_cv_prog_CC="cl" break fi done IFS="$ac_save_ifs" fi fi CC="$ac_cv_prog_CC" if test -n "$CC"; then echo "$ac_t""$CC" 1>&6 else echo "$ac_t""no" 1>&6 fi ;; esac fi test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 echo "configure:906: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. ac_cpp='$CPP $CPPFLAGS' ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' cross_compiling=$ac_cv_prog_cc_cross cat > conftest.$ac_ext << EOF #line 917 "configure" #include "confdefs.h" main(){return(0);} EOF if { (eval echo configure:922: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then ac_cv_prog_cc_works=yes # If we can't run a trivial program, we are probably using a cross compiler. if (./conftest; exit) 2>/dev/null; then ac_cv_prog_cc_cross=no else ac_cv_prog_cc_cross=yes fi else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 ac_cv_prog_cc_works=no fi rm -fr conftest* ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. ac_cpp='$CPP $CPPFLAGS' ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' cross_compiling=$ac_cv_prog_cc_cross echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 if test $ac_cv_prog_cc_works = no; then { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 echo "configure:948: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 cross_compiling=$ac_cv_prog_cc_cross echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 echo "configure:953: checking whether we are using GNU C" >&5 if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then ac_cv_prog_gcc=yes else ac_cv_prog_gcc=no fi fi echo "$ac_t""$ac_cv_prog_gcc" 1>&6 if test $ac_cv_prog_gcc = yes; then GCC=yes else GCC= fi ac_test_CFLAGS="${CFLAGS+set}" ac_save_CFLAGS="$CFLAGS" CFLAGS= echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 echo "configure:981: checking whether ${CC-cc} accepts -g" >&5 if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else echo 'void f(){}' > conftest.c if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then ac_cv_prog_cc_g=yes else ac_cv_prog_cc_g=no fi rm -f conftest* fi echo "$ac_t""$ac_cv_prog_cc_g" 1>&6 if test "$ac_test_CFLAGS" = set; then CFLAGS="$ac_save_CFLAGS" elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # ./install, which can be erroneously created by make from ./install.sh. echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 echo "configure:1024: checking for a BSD compatible install" >&5 if test -z "$INSTALL"; then if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":" for ac_dir in $PATH; do # Account for people who put trailing slashes in PATH elements. case "$ac_dir/" in /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do if test -f $ac_dir/$ac_prog; then if test $ac_prog = install && grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : else ac_cv_path_install="$ac_dir/$ac_prog -c" break 2 fi fi done ;; esac done IFS="$ac_save_IFS" fi if test "${ac_cv_path_install+set}" = set; then INSTALL="$ac_cv_path_install" else # As a last resort, use the slow shell script. We don't cache a # path for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the path is relative. INSTALL="$ac_install_sh" fi fi echo "$ac_t""$INSTALL" 1>&6 # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6 echo "configure:1077: checking whether ln -s works" >&5 if eval "test \"`echo '$''{'ac_cv_prog_LN_S'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else rm -f conftestdata if ln -s X conftestdata 2>/dev/null then rm -f conftestdata ac_cv_prog_LN_S="ln -s" else ac_cv_prog_LN_S=ln fi fi LN_S="$ac_cv_prog_LN_S" if test "$ac_cv_prog_LN_S" = "ln -s"; then echo "$ac_t""yes" 1>&6 else echo "$ac_t""no" 1>&6 fi echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 echo "configure:1098: checking whether ${MAKE-make} sets \${MAKE}" >&5 set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftestmake <<\EOF all: @echo 'ac_maketemp="${MAKE}"' EOF # GNU make sometimes prints "make[1]: Entering...", which would confuse us. eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=` if test -n "$ac_maketemp"; then eval ac_cv_prog_make_${ac_make}_set=yes else eval ac_cv_prog_make_${ac_make}_set=no fi rm -f conftestmake fi if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then echo "$ac_t""yes" 1>&6 SET_MAKE= else echo "$ac_t""no" 1>&6 SET_MAKE="MAKE=${MAKE-make}" fi CFLAGS="-DMATANZA_ASSERT=1 -DMATANZA_VERBOSE=1" # Check whether --enable-profile or --disable-profile was given. if test "${enable_profile+set}" = set; then enableval="$enable_profile" if test "x$enable_profile" = xyes; then CFLAGS="-pg $CFLAGS" fi fi # Check whether --enable-debug or --disable-debug was given. if test "${enable_debug+set}" = set; then enableval="$enable_debug" if test "x$enable_debug" = xyes; then CFLAGS="-g $CFLAGS" fi fi # Check whether --enable-efence or --disable-efence was given. if test "${enable_efence+set}" = set; then enableval="$enable_efence" if test "x$enable_efence" = xyes; then echo $ac_n "checking for malloc in -lefence""... $ac_c" 1>&6 echo "configure:1153: checking for malloc in -lefence" >&5 ac_lib_var=`echo efence'_'malloc | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lefence $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi rm -f conftest* LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 ac_tr_lib=HAVE_LIB`echo efence | sed -e 's/^a-zA-Z0-9_/_/g' \ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` cat >> confdefs.h <&6 fi fi fi echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 echo "configure:1205: checking how to run the C preprocessor" >&5 # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # This must be in double quotes, not single quotes, because CPP may get # substituted into the Makefile and "${CC-cc}" will confuse make. CPP="${CC-cc} -E" # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" { (eval echo configure:1226: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : else echo "$ac_err" >&5 echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* CPP="${CC-cc} -E -traditional-cpp" cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" { (eval echo configure:1243: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : else echo "$ac_err" >&5 echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* CPP="${CC-cc} -nologo -E" cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" { (eval echo configure:1260: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : else echo "$ac_err" >&5 echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* CPP=/lib/cpp fi rm -f conftest* fi rm -f conftest* fi rm -f conftest* ac_cv_prog_CPP="$CPP" fi CPP="$ac_cv_prog_CPP" else ac_cv_prog_CPP="$CPP" fi echo "$ac_t""$CPP" 1>&6 for ac_hdr in png.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 echo "configure:1288: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" { (eval echo configure:1298: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* eval "ac_cv_header_$ac_safe=yes" else echo "$ac_err" >&5 echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_header_$ac_safe=no" fi rm -f conftest* fi if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then echo "$ac_t""yes" 1>&6 ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` cat >> confdefs.h <&6 fi done echo $ac_n "checking for png_sig_cmp in -lpng""... $ac_c" 1>&6 echo "configure:1326: checking for png_sig_cmp in -lpng" >&5 ac_lib_var=`echo png'_'png_sig_cmp | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lpng $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi rm -f conftest* LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 LIBS="$LIBS -lpng" HAVE_LIBPNG="1" cat >> confdefs.h <&6 HAVE_LIBPNG="0" fi echo $ac_n "checking for sin in -lm""... $ac_c" 1>&6 echo "configure:1377: checking for sin in -lm" >&5 ac_lib_var=`echo m'_'sin | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lm $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi rm -f conftest* LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 ac_tr_lib=HAVE_LIB`echo m | sed -e 's/[^a-zA-Z0-9_]/_/g' \ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` cat >> confdefs.h <&6 fi CFLAGS="$CFLAGS -DXML_MIN_SIZE" echo $ac_n "checking for socket in -lsocket""... $ac_c" 1>&6 echo "configure:1430: checking for socket in -lsocket" >&5 ac_lib_var=`echo socket'_'socket | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lsocket $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi rm -f conftest* LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 ac_tr_lib=HAVE_LIB`echo socket | sed -e 's/[^a-zA-Z0-9_]/_/g' \ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` cat >> confdefs.h <&6 fi echo $ac_n "checking for inet_ntoa in -lnsl""... $ac_c" 1>&6 echo "configure:1477: checking for inet_ntoa in -lnsl" >&5 ac_lib_var=`echo nsl'_'inet_ntoa | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lnsl $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi rm -f conftest* LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 ac_tr_lib=HAVE_LIB`echo nsl | sed -e 's/[^a-zA-Z0-9_]/_/g' \ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` cat >> confdefs.h <&6 fi echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 echo "configure:1526: checking for ANSI C header files" >&5 if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include #include #include EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" { (eval echo configure:1539: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* ac_cv_header_stdc=yes else echo "$ac_err" >&5 echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* ac_cv_header_stdc=no fi rm -f conftest* if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat > conftest.$ac_ext < EOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | egrep "memchr" >/dev/null 2>&1; then : else rm -rf conftest* ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat > conftest.$ac_ext < EOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | egrep "free" >/dev/null 2>&1; then : else rm -rf conftest* ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : else cat > conftest.$ac_ext < #define ISLOWER(c) ('a' <= (c) && (c) <= 'z') #define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); exit (0); } EOF if { (eval echo configure:1606: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then : else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -fr conftest* ac_cv_header_stdc=no fi rm -fr conftest* fi fi fi echo "$ac_t""$ac_cv_header_stdc" 1>&6 if test $ac_cv_header_stdc = yes; then cat >> confdefs.h <<\EOF #define STDC_HEADERS 1 EOF fi for ac_hdr in fcntl.h limits.h unistd.h arpa/telnet.h netdb.h netinet/in.h arpa/inet.h sys/ioctl.h sys/time.h sys/types.h sys/socket.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 echo "configure:1634: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" { (eval echo configure:1644: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* eval "ac_cv_header_$ac_safe=yes" else echo "$ac_err" >&5 echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_header_$ac_safe=no" fi rm -f conftest* fi if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then echo "$ac_t""yes" 1>&6 ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` cat >> confdefs.h <&6 fi done for ac_hdr in winsock2.h windows.h direct.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 echo "configure:1675: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" { (eval echo configure:1685: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* eval "ac_cv_header_$ac_safe=yes" else echo "$ac_err" >&5 echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_header_$ac_safe=no" fi rm -f conftest* fi if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then echo "$ac_t""yes" 1>&6 ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` cat >> confdefs.h <&6 fi done for ac_hdr in OS.h Errors.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 echo "configure:1716: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" { (eval echo configure:1726: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* eval "ac_cv_header_$ac_safe=yes" else echo "$ac_err" >&5 echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_header_$ac_safe=no" fi rm -f conftest* fi if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then echo "$ac_t""yes" 1>&6 ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` cat >> confdefs.h <&6 fi done echo $ac_n "checking for working const""... $ac_c" 1>&6 echo "configure:1755: checking for working const" >&5 if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <j = 5; } { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ const int foo = 10; } ; return 0; } EOF if { (eval echo configure:1809: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_const=yes else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* ac_cv_c_const=no fi rm -f conftest* fi echo "$ac_t""$ac_cv_c_const" 1>&6 if test $ac_cv_c_const = no; then cat >> confdefs.h <<\EOF #define const EOF fi echo $ac_n "checking for size_t""... $ac_c" 1>&6 echo "configure:1830: checking for size_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS #include #include #endif EOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | egrep "(^|[^a-zA-Z_0-9])size_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then rm -rf conftest* ac_cv_type_size_t=yes else rm -rf conftest* ac_cv_type_size_t=no fi rm -f conftest* fi echo "$ac_t""$ac_cv_type_size_t" 1>&6 if test $ac_cv_type_size_t = no; then cat >> confdefs.h <<\EOF #define size_t unsigned EOF fi echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6 echo "configure:1863: checking whether time.h and sys/time.h may both be included" >&5 if eval "test \"`echo '$''{'ac_cv_header_time'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include #include int main() { struct tm *tp; ; return 0; } EOF if { (eval echo configure:1877: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_header_time=yes else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* ac_cv_header_time=no fi rm -f conftest* fi echo "$ac_t""$ac_cv_header_time" 1>&6 if test $ac_cv_header_time = yes; then cat >> confdefs.h <<\EOF #define TIME_WITH_SYS_TIME 1 EOF fi echo $ac_n "checking whether struct tm is in sys/time.h or time.h""... $ac_c" 1>&6 echo "configure:1898: checking whether struct tm is in sys/time.h or time.h" >&5 if eval "test \"`echo '$''{'ac_cv_struct_tm'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include int main() { struct tm *tp; tp->tm_sec; ; return 0; } EOF if { (eval echo configure:1911: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_struct_tm=time.h else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* ac_cv_struct_tm=sys/time.h fi rm -f conftest* fi echo "$ac_t""$ac_cv_struct_tm" 1>&6 if test $ac_cv_struct_tm = sys/time.h; then cat >> confdefs.h <<\EOF #define TM_IN_SYS_TIME 1 EOF fi echo $ac_n "checking for socklen_t""... $ac_c" 1>&6 echo "configure:1932: checking for socklen_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_socklen_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include int main() { socklen_t len = 42; return 0; ; return 0; } EOF if { (eval echo configure:1946: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_type_socklen_t=yes else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* ac_cv_type_socklen_t=no fi rm -f conftest* fi echo "$ac_t""$ac_cv_type_socklen_t" 1>&6 if test $ac_cv_type_socklen_t != yes; then cat >> confdefs.h <<\EOF #define socklen_t int EOF fi echo $ac_n "checking for 8-bit clean memcmp""... $ac_c" 1>&6 echo "configure:1970: checking for 8-bit clean memcmp" >&5 if eval "test \"`echo '$''{'ac_cv_func_memcmp_clean'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then ac_cv_func_memcmp_clean=no else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_func_memcmp_clean=yes else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -fr conftest* ac_cv_func_memcmp_clean=no fi rm -fr conftest* fi fi echo "$ac_t""$ac_cv_func_memcmp_clean" 1>&6 test $ac_cv_func_memcmp_clean = no && LIBOBJS="$LIBOBJS memcmp.${ac_objext}" echo $ac_n "checking for vprintf""... $ac_c" 1>&6 echo "configure:2006: checking for vprintf" >&5 if eval "test \"`echo '$''{'ac_cv_func_vprintf'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char vprintf(); int main() { /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_vprintf) || defined (__stub___vprintf) choke me #else vprintf(); #endif ; return 0; } EOF if { (eval echo configure:2034: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_vprintf=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_func_vprintf=no" fi rm -f conftest* fi if eval "test \"`echo '$ac_cv_func_'vprintf`\" = yes"; then echo "$ac_t""yes" 1>&6 cat >> confdefs.h <<\EOF #define HAVE_VPRINTF 1 EOF else echo "$ac_t""no" 1>&6 fi if test "$ac_cv_func_vprintf" != yes; then echo $ac_n "checking for _doprnt""... $ac_c" 1>&6 echo "configure:2058: checking for _doprnt" >&5 if eval "test \"`echo '$''{'ac_cv_func__doprnt'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char _doprnt(); int main() { /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub__doprnt) || defined (__stub____doprnt) choke me #else _doprnt(); #endif ; return 0; } EOF if { (eval echo configure:2086: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func__doprnt=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_func__doprnt=no" fi rm -f conftest* fi if eval "test \"`echo '$ac_cv_func_'_doprnt`\" = yes"; then echo "$ac_t""yes" 1>&6 cat >> confdefs.h <<\EOF #define HAVE_DOPRNT 1 EOF else echo "$ac_t""no" 1>&6 fi fi for ac_func in signal fork setsid socket fcntl strerror strspn inet_ntop inet_ntoa ioctlsocket hstrerror usleep Sleep gettimeofday snooze_until system_time GetTickCount setsockopt WSASocket WSAStartup closesocket umask do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 echo "configure:2113: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char $ac_func(); int main() { /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else $ac_func(); #endif ; return 0; } EOF if { (eval echo configure:2141: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_func_$ac_func=no" fi rm -f conftest* fi if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then echo "$ac_t""yes" 1>&6 ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` cat >> confdefs.h <&6 fi done trap '' 1 2 15 cat > confcache <<\EOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs. It is not useful on other systems. # If it contains results you don't want to keep, you may remove or edit it. # # By default, configure uses ./config.cache as the cache file, # creating it if it does not exist already. You can give configure # the --cache-file=FILE option to use a different cache file; that is # what configure does when it calls configure scripts in # subdirectories, so they share the cache. # Giving --cache-file=/dev/null disables caching, for debugging configure. # config.status only pays attention to the cache file if you give it the # --recheck option to rerun configure. # EOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, don't put newlines in cache variables' values. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. (set) 2>&1 | case `(ac_space=' '; set | grep ac_space) 2>&1` in *ac_space=\ *) # `set' does not quote correctly, so add quotes (double-quote substitution # turns \\\\ into \\, and sed turns \\ into \). sed -n \ -e "s/'/'\\\\''/g" \ -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" ;; *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' ;; esac >> confcache if cmp -s $cache_file confcache; then : else if test -w $cache_file; then echo "updating cache $cache_file" cat confcache > $cache_file else echo "not updating unwritable cache $cache_file" fi fi rm -f confcache trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # Any assignment to VPATH causes Sun make to only execute # the first set of double-colon rules, so remove it if not needed. # If there is a colon in the path, we need to keep it. if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' fi trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 DEFS=-DHAVE_CONFIG_H # Without the "./", some shells look in PATH for config.status. : ${CONFIG_STATUS=./config.status} echo creating $CONFIG_STATUS rm -f $CONFIG_STATUS cat > $CONFIG_STATUS </dev/null | sed 1q`: # # $0 $ac_configure_args # # Compiler output produced by configure, useful for debugging # configure, is in ./config.log if it exists. ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" for ac_option do case "\$ac_option" in -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; -version | --version | --versio | --versi | --vers | --ver | --ve | --v) echo "$CONFIG_STATUS generated by autoconf version 2.13" exit 0 ;; -help | --help | --hel | --he | --h) echo "\$ac_cs_usage"; exit 0 ;; *) echo "\$ac_cs_usage"; exit 1 ;; esac done ac_given_srcdir=$srcdir ac_given_INSTALL="$INSTALL" trap 'rm -fr `echo "Makefile config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 EOF cat >> $CONFIG_STATUS < conftest.subs <<\\CEOF $ac_vpsub $extrasub s%@SHELL@%$SHELL%g s%@CFLAGS@%$CFLAGS%g s%@CPPFLAGS@%$CPPFLAGS%g s%@CXXFLAGS@%$CXXFLAGS%g s%@FFLAGS@%$FFLAGS%g s%@DEFS@%$DEFS%g s%@LDFLAGS@%$LDFLAGS%g s%@LIBS@%$LIBS%g s%@exec_prefix@%$exec_prefix%g s%@prefix@%$prefix%g s%@program_transform_name@%$program_transform_name%g s%@bindir@%$bindir%g s%@sbindir@%$sbindir%g s%@libexecdir@%$libexecdir%g s%@datadir@%$datadir%g s%@sysconfdir@%$sysconfdir%g s%@sharedstatedir@%$sharedstatedir%g s%@localstatedir@%$localstatedir%g s%@libdir@%$libdir%g s%@includedir@%$includedir%g s%@oldincludedir@%$oldincludedir%g s%@infodir@%$infodir%g s%@mandir@%$mandir%g s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g s%@INSTALL_DATA@%$INSTALL_DATA%g s%@PACKAGE@%$PACKAGE%g s%@VERSION@%$VERSION%g s%@ACLOCAL@%$ACLOCAL%g s%@AUTOCONF@%$AUTOCONF%g s%@AUTOMAKE@%$AUTOMAKE%g s%@AUTOHEADER@%$AUTOHEADER%g s%@MAKEINFO@%$MAKEINFO%g s%@SET_MAKE@%$SET_MAKE%g s%@CC@%$CC%g s%@LN_S@%$LN_S%g s%@CPP@%$CPP%g s%@LIBOBJS@%$LIBOBJS%g CEOF EOF cat >> $CONFIG_STATUS <<\EOF # Split the substitutions into bite-sized pieces for seds with # small command number limits, like on Digital OSF/1 and HP-UX. ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. ac_file=1 # Number of current file. ac_beg=1 # First line for current file. ac_end=$ac_max_sed_cmds # Line after last line for current file. ac_more_lines=: ac_sed_cmds="" while $ac_more_lines; do if test $ac_beg -gt 1; then sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file else sed "${ac_end}q" conftest.subs > conftest.s$ac_file fi if test ! -s conftest.s$ac_file; then ac_more_lines=false rm -f conftest.s$ac_file else if test -z "$ac_sed_cmds"; then ac_sed_cmds="sed -f conftest.s$ac_file" else ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" fi ac_file=`expr $ac_file + 1` ac_beg=$ac_end ac_end=`expr $ac_end + $ac_max_sed_cmds` fi done if test -z "$ac_sed_cmds"; then ac_sed_cmds=cat fi EOF cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". case "$ac_file" in *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; *) ac_file_in="${ac_file}.in" ;; esac # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. # Remove last slash and all that follows it. Not all systems have dirname. ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then # The file is in a subdirectory. test ! -d "$ac_dir" && mkdir "$ac_dir" ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" # A "../" for each directory in $ac_dir_suffix. ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` else ac_dir_suffix= ac_dots= fi case "$ac_given_srcdir" in .) srcdir=. if test -z "$ac_dots"; then top_srcdir=. else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; *) # Relative path. srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" top_srcdir="$ac_dots$ac_given_srcdir" ;; esac case "$ac_given_INSTALL" in [/$]*) INSTALL="$ac_given_INSTALL" ;; *) INSTALL="$ac_dots$ac_given_INSTALL" ;; esac echo creating "$ac_file" rm -f "$ac_file" configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." case "$ac_file" in *Makefile*) ac_comsub="1i\\ # $configure_input" ;; *) ac_comsub= ;; esac ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` sed -e "$ac_comsub s%@configure_input@%$configure_input%g s%@srcdir@%$srcdir%g s%@top_srcdir@%$top_srcdir%g s%@INSTALL@%$INSTALL%g " $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file fi; done rm -f conftest.s* # These sed commands are passed to sed as "A NAME B NAME C VALUE D", where # NAME is the cpp macro being defined and VALUE is the value it is being given. # # ac_d sets the value in "#define NAME VALUE" lines. ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)' ac_dB='\([ ][ ]*\)[^ ]*%\1#\2' ac_dC='\3' ac_dD='%g' # ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE". ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' ac_uB='\([ ]\)%\1#\2define\3' ac_uC=' ' ac_uD='\4%g' # ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE". ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' ac_eB='$%\1#\2define\3' ac_eC=' ' ac_eD='%g' if test "${CONFIG_HEADERS+set}" != set; then EOF cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF fi for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". case "$ac_file" in *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; *) ac_file_in="${ac_file}.in" ;; esac echo creating $ac_file rm -f conftest.frag conftest.in conftest.out ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` cat $ac_file_inputs > conftest.in EOF # Transform confdefs.h into a sed script conftest.vals that substitutes # the proper values into config.h.in to produce config.h. And first: # Protect against being on the right side of a sed subst in config.status. # Protect against being in an unquoted here document in config.status. rm -f conftest.vals cat > conftest.hdr <<\EOF s/[\\&%]/\\&/g s%[\\$`]%\\&%g s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp s%ac_d%ac_u%gp s%ac_u%ac_e%gp EOF sed -n -f conftest.hdr confdefs.h > conftest.vals rm -f conftest.hdr # This sed command replaces #undef with comments. This is necessary, for # example, in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. cat >> conftest.vals <<\EOF s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */% EOF # Break up conftest.vals because some shells have a limit on # the size of here documents, and old seds have small limits too. rm -f conftest.tail while : do ac_lines=`grep -c . conftest.vals` # grep -c gives empty output for an empty file on some AIX systems. if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi # Write a limited-size here document to conftest.frag. echo ' cat > conftest.frag <> $CONFIG_STATUS sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS echo 'CEOF sed -f conftest.frag conftest.in > conftest.out rm -f conftest.in mv conftest.out conftest.in ' >> $CONFIG_STATUS sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail rm -f conftest.vals mv conftest.tail conftest.vals done rm -f conftest.vals cat >> $CONFIG_STATUS <<\EOF rm -f conftest.frag conftest.h echo "/* $ac_file. Generated automatically by configure. */" > conftest.h cat conftest.in >> conftest.h rm -f conftest.in if cmp -s $ac_file conftest.h 2>/dev/null; then echo "$ac_file is unchanged" rm -f conftest.h else # Remove last slash and all that follows it. Not all systems have dirname. ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then # The file is in a subdirectory. test ! -d "$ac_dir" && mkdir "$ac_dir" fi rm -f $ac_file mv conftest.h $ac_file fi fi; done EOF cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF test -z "$CONFIG_HEADERS" || echo timestamp > stamp-h exit 0 EOF chmod +x $CONFIG_STATUS rm -fr confdefs* $ac_clean_files test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 matanza-0.13/INSTALL0000644000175000017500000001722707107673450014313 0ustar boradminboradminBasic Installation ================== These are generic installation instructions. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a `Makefile' in each directory of the package. It may also create one or more `.h' files containing system-dependent definitions. Finally, it creates a shell script `config.status' that you can run in the future to recreate the current configuration, a file `config.cache' that saves the results of its tests to speed up reconfiguring, and a file `config.log' containing compiler output (useful mainly for debugging `configure'). If you need to do unusual things to compile the package, please try to figure out how `configure' could check whether to do them, and mail diffs or instructions to the address given in the `README' so they can be considered for the next release. If at some point `config.cache' contains results you don't want to keep, you may remove or edit it. The file `configure.in' is used to create `configure' by a program called `autoconf'. You only need `configure.in' if you want to change it or regenerate `configure' using a newer version of `autoconf'. The simplest way to compile this package is: 1. `cd' to the directory containing the package's source code and type `./configure' to configure the package for your system. If you're using `csh' on an old version of System V, you might need to type `sh ./configure' instead to prevent `csh' from trying to execute `configure' itself. Running `configure' takes awhile. While running, it prints some messages telling which features it is checking for. 2. Type `make' to compile the package. 3. Optionally, type `make check' to run any self-tests that come with the package. 4. Type `make install' to install the programs and any data files and documentation. 5. You can remove the program binaries and object files from the source code directory by typing `make clean'. To also remove the files that `configure' created (so you can compile the package for a different kind of computer), type `make distclean'. There is also a `make maintainer-clean' target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. Compilers and Options ===================== Some systems require unusual options for compilation or linking that the `configure' script does not know about. You can give `configure' initial values for variables by setting them in the environment. Using a Bourne-compatible shell, you can do that on the command line like this: CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure Or on systems that have the `env' program, you can do it like this: env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure Compiling For Multiple Architectures ==================================== You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you must use a version of `make' that supports the `VPATH' variable, such as GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the source code in the directory that `configure' is in and in `..'. If you have to use a `make' that does not supports the `VPATH' variable, you have to compile the package for one architecture at a time in the source code directory. After you have installed the package for one architecture, use `make distclean' before reconfiguring for another architecture. Installation Names ================== By default, `make install' will install the package's files in `/usr/local/bin', `/usr/local/man', etc. You can specify an installation prefix other than `/usr/local' by giving `configure' the option `--prefix=PATH'. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you give `configure' the option `--exec-prefix=PATH', the package will use PATH as the prefix for installing programs and libraries. Documentation and other data files will still use the regular prefix. In addition, if you use an unusual directory layout you can give options like `--bindir=PATH' to specify different values for particular kinds of files. Run `configure --help' for a list of the directories you can set and what kinds of files go in them. If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving `configure' the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. Optional Features ================= Some packages pay attention to `--enable-FEATURE' options to `configure', where FEATURE indicates an optional part of the package. They may also pay attention to `--with-PACKAGE' options, where PACKAGE is something like `gnu-as' or `x' (for the X Window System). The `README' should mention any `--enable-' and `--with-' options that the package recognizes. For packages that use the X Window System, `configure' can usually find the X include and library files automatically, but if it doesn't, you can use the `configure' options `--x-includes=DIR' and `--x-libraries=DIR' to specify their locations. Specifying the System Type ========================== There may be some features `configure' can not figure out automatically, but needs to determine by the type of host the package will run on. Usually `configure' can figure that out, but if it prints a message saying it can not guess the host type, give it the `--host=TYPE' option. TYPE can either be a short name for the system type, such as `sun4', or a canonical name with three fields: CPU-COMPANY-SYSTEM See the file `config.sub' for the possible values of each field. If `config.sub' isn't included in this package, then this package doesn't need to know the host type. If you are building compiler tools for cross-compiling, you can also use the `--target=TYPE' option to select the type of system they will produce code for and the `--build=TYPE' option to select the type of system on which you are compiling the package. Sharing Defaults ================ If you want to set default values for `configure' scripts to share, you can create a site shell script called `config.site' that gives default values for variables like `CC', `cache_file', and `prefix'. `configure' looks for `PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it exists. Or, you can set the `CONFIG_SITE' environment variable to the location of the site script. A warning: not all `configure' scripts look for a site script. Operation Controls ================== `configure' recognizes the following options to control how it operates. `--cache-file=FILE' Use and save the results of the tests in FILE instead of `./config.cache'. Set FILE to `/dev/null' to disable caching, for debugging `configure'. `--help' Print a summary of the options to `configure', and exit. `--quiet' `--silent' `-q' Do not print messages saying which checks are being made. To suppress all normal output, redirect it to `/dev/null' (any error messages will still be shown). `--srcdir=DIR' Look for the package's source code in directory DIR. Usually `configure' can determine that directory automatically. `--version' Print the version of Autoconf used to generate the `configure' script, and exit. `configure' also accepts some other, not widely useful, options. matanza-0.13/xmlparse.c0000644000175000017500000032216707254522236015261 0ustar boradminboradmin/* Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd See the file copying.txt for copying permission. */ #include "xmldef.h" #include "xmlparse.h" #include #ifdef XML_UNICODE #define XML_ENCODE_MAX XML_UTF16_ENCODE_MAX #define XmlConvert XmlUtf16Convert #define XmlGetInternalEncoding XmlGetUtf16InternalEncoding #define XmlGetInternalEncodingNS XmlGetUtf16InternalEncodingNS #define XmlEncode XmlUtf16Encode #define MUST_CONVERT(enc, s) (!(enc)->isUtf16 || (((unsigned long)s) & 1)) typedef unsigned short ICHAR; #else #define XML_ENCODE_MAX XML_UTF8_ENCODE_MAX #define XmlConvert XmlUtf8Convert #define XmlGetInternalEncoding XmlGetUtf8InternalEncoding #define XmlGetInternalEncodingNS XmlGetUtf8InternalEncodingNS #define XmlEncode XmlUtf8Encode #define MUST_CONVERT(enc, s) (!(enc)->isUtf8) typedef char ICHAR; #endif #ifndef XML_NS #define XmlInitEncodingNS XmlInitEncoding #define XmlInitUnknownEncodingNS XmlInitUnknownEncoding #undef XmlGetInternalEncodingNS #define XmlGetInternalEncodingNS XmlGetInternalEncoding #define XmlParseXmlDeclNS XmlParseXmlDecl #endif #ifdef XML_UNICODE_WCHAR_T #define XML_T(x) L ## x #else #define XML_T(x) x #endif /* Round up n to be a multiple of sz, where sz is a power of 2. */ #define ROUND_UP(n, sz) (((n) + ((sz) - 1)) & ~((sz) - 1)) #include "xmltok.h" #include "xmlrole.h" typedef const XML_Char *KEY; typedef struct { KEY name; } NAMED; typedef struct { NAMED **v; size_t size; size_t used; size_t usedLim; } HASH_TABLE; typedef struct { NAMED **p; NAMED **end; } HASH_TABLE_ITER; #define INIT_TAG_BUF_SIZE 32 /* must be a multiple of sizeof(XML_Char) */ #define INIT_DATA_BUF_SIZE 1024 #define INIT_ATTS_SIZE 16 #define INIT_BLOCK_SIZE 1024 #define INIT_BUFFER_SIZE 1024 #define EXPAND_SPARE 24 typedef struct binding { struct prefix *prefix; struct binding *nextTagBinding; struct binding *prevPrefixBinding; const struct attribute_id *attId; XML_Char *uri; int uriLen; int uriAlloc; } BINDING; typedef struct prefix { const XML_Char *name; BINDING *binding; } PREFIX; typedef struct { const XML_Char *str; const XML_Char *localPart; int uriLen; } TAG_NAME; typedef struct tag { struct tag *parent; const char *rawName; int rawNameLength; TAG_NAME name; char *buf; char *bufEnd; BINDING *bindings; } TAG; typedef struct { const XML_Char *name; const XML_Char *textPtr; int textLen; const XML_Char *systemId; const XML_Char *base; const XML_Char *publicId; const XML_Char *notation; char open; } ENTITY; typedef struct block { struct block *next; int size; XML_Char s[1]; } BLOCK; typedef struct { BLOCK *blocks; BLOCK *freeBlocks; const XML_Char *end; XML_Char *ptr; XML_Char *start; } STRING_POOL; /* The XML_Char before the name is used to determine whether an attribute has been specified. */ typedef struct attribute_id { XML_Char *name; PREFIX *prefix; char maybeTokenized; char xmlns; } ATTRIBUTE_ID; typedef struct { const ATTRIBUTE_ID *id; char isCdata; const XML_Char *value; } DEFAULT_ATTRIBUTE; typedef struct { const XML_Char *name; PREFIX *prefix; const ATTRIBUTE_ID *idAtt; int nDefaultAtts; int allocDefaultAtts; DEFAULT_ATTRIBUTE *defaultAtts; } ELEMENT_TYPE; typedef struct { HASH_TABLE generalEntities; HASH_TABLE elementTypes; HASH_TABLE attributeIds; HASH_TABLE prefixes; STRING_POOL pool; int complete; int standalone; #ifdef XML_DTD HASH_TABLE paramEntities; #endif /* XML_DTD */ PREFIX defaultPrefix; } DTD; typedef struct open_internal_entity { const char *internalEventPtr; const char *internalEventEndPtr; struct open_internal_entity *next; ENTITY *entity; } OPEN_INTERNAL_ENTITY; typedef enum XML_Error Processor(XML_Parser parser, const char *start, const char *end, const char **endPtr); static Processor prologProcessor; static Processor prologInitProcessor; static Processor contentProcessor; static Processor cdataSectionProcessor; #ifdef XML_DTD static Processor ignoreSectionProcessor; #endif /* XML_DTD */ static Processor epilogProcessor; static Processor errorProcessor; static Processor externalEntityInitProcessor; static Processor externalEntityInitProcessor2; static Processor externalEntityInitProcessor3; static Processor externalEntityContentProcessor; static enum XML_Error handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName); static enum XML_Error processXmlDecl(XML_Parser parser, int isGeneralTextEntity, const char *, const char *); static enum XML_Error initializeEncoding(XML_Parser parser); static enum XML_Error doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end, int tok, const char *next, const char **nextPtr); static enum XML_Error processInternalParamEntity(XML_Parser parser, ENTITY *entity); static enum XML_Error doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc, const char *start, const char *end, const char **endPtr); static enum XML_Error doCdataSection(XML_Parser parser, const ENCODING *, const char **startPtr, const char *end, const char **nextPtr); #ifdef XML_DTD static enum XML_Error doIgnoreSection(XML_Parser parser, const ENCODING *, const char **startPtr, const char *end, const char **nextPtr); #endif /* XML_DTD */ static enum XML_Error storeAtts(XML_Parser parser, const ENCODING *, const char *s, TAG_NAME *tagNamePtr, BINDING **bindingsPtr); static int addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, const XML_Char *uri, BINDING **bindingsPtr); static int defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *, int isCdata, int isId, const XML_Char *dfltValue); static enum XML_Error storeAttributeValue(XML_Parser parser, const ENCODING *, int isCdata, const char *, const char *, STRING_POOL *); static enum XML_Error appendAttributeValue(XML_Parser parser, const ENCODING *, int isCdata, const char *, const char *, STRING_POOL *); static ATTRIBUTE_ID * getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start, const char *end); static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *); static enum XML_Error storeEntityValue(XML_Parser parser, const ENCODING *enc, const char *start, const char *end); static int reportProcessingInstruction(XML_Parser parser, const ENCODING *enc, const char *start, const char *end); static int reportComment(XML_Parser parser, const ENCODING *enc, const char *start, const char *end); static void reportDefault(XML_Parser parser, const ENCODING *enc, const char *start, const char *end); static const XML_Char *getContext(XML_Parser parser); static int setContext(XML_Parser parser, const XML_Char *context); static void normalizePublicId(XML_Char *s); static int dtdInit(DTD *); static void dtdDestroy(DTD *); static int dtdCopy(DTD *newDtd, const DTD *oldDtd); static int copyEntityTable(HASH_TABLE *, STRING_POOL *, const HASH_TABLE *); #ifdef XML_DTD static void dtdSwap(DTD *, DTD *); #endif /* XML_DTD */ static NAMED *lookup(HASH_TABLE *table, KEY name, size_t createSize); static void hashTableInit(HASH_TABLE *); static void hashTableDestroy(HASH_TABLE *); static void hashTableIterInit(HASH_TABLE_ITER *, const HASH_TABLE *); static NAMED *hashTableIterNext(HASH_TABLE_ITER *); static void poolInit(STRING_POOL *); static void poolClear(STRING_POOL *); static void poolDestroy(STRING_POOL *); static XML_Char *poolAppend(STRING_POOL *pool, const ENCODING *enc, const char *ptr, const char *end); static XML_Char *poolStoreString(STRING_POOL *pool, const ENCODING *enc, const char *ptr, const char *end); static int poolGrow(STRING_POOL *pool); static const XML_Char *poolCopyString(STRING_POOL *pool, const XML_Char *s); static const XML_Char *poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n); #define poolStart(pool) ((pool)->start) #define poolEnd(pool) ((pool)->ptr) #define poolLength(pool) ((pool)->ptr - (pool)->start) #define poolChop(pool) ((void)--(pool->ptr)) #define poolLastChar(pool) (((pool)->ptr)[-1]) #define poolDiscard(pool) ((pool)->ptr = (pool)->start) #define poolFinish(pool) ((pool)->start = (pool)->ptr) #define poolAppendChar(pool, c) \ (((pool)->ptr == (pool)->end && !poolGrow(pool)) \ ? 0 \ : ((*((pool)->ptr)++ = c), 1)) typedef struct { /* The first member must be userData so that the XML_GetUserData macro works. */ void *m_userData; void *m_handlerArg; char *m_buffer; /* first character to be parsed */ const char *m_bufferPtr; /* past last character to be parsed */ char *m_bufferEnd; /* allocated end of buffer */ const char *m_bufferLim; long m_parseEndByteIndex; const char *m_parseEndPtr; XML_Char *m_dataBuf; XML_Char *m_dataBufEnd; XML_StartElementHandler m_startElementHandler; XML_EndElementHandler m_endElementHandler; XML_CharacterDataHandler m_characterDataHandler; XML_ProcessingInstructionHandler m_processingInstructionHandler; XML_CommentHandler m_commentHandler; XML_StartCdataSectionHandler m_startCdataSectionHandler; XML_EndCdataSectionHandler m_endCdataSectionHandler; XML_DefaultHandler m_defaultHandler; XML_StartDoctypeDeclHandler m_startDoctypeDeclHandler; XML_EndDoctypeDeclHandler m_endDoctypeDeclHandler; XML_UnparsedEntityDeclHandler m_unparsedEntityDeclHandler; XML_NotationDeclHandler m_notationDeclHandler; XML_ExternalParsedEntityDeclHandler m_externalParsedEntityDeclHandler; XML_InternalParsedEntityDeclHandler m_internalParsedEntityDeclHandler; XML_StartNamespaceDeclHandler m_startNamespaceDeclHandler; XML_EndNamespaceDeclHandler m_endNamespaceDeclHandler; XML_NotStandaloneHandler m_notStandaloneHandler; XML_ExternalEntityRefHandler m_externalEntityRefHandler; void *m_externalEntityRefHandlerArg; XML_UnknownEncodingHandler m_unknownEncodingHandler; const ENCODING *m_encoding; INIT_ENCODING m_initEncoding; const ENCODING *m_internalEncoding; const XML_Char *m_protocolEncodingName; int m_ns; void *m_unknownEncodingMem; void *m_unknownEncodingData; void *m_unknownEncodingHandlerData; void (*m_unknownEncodingRelease)(void *); PROLOG_STATE m_prologState; Processor *m_processor; enum XML_Error m_errorCode; const char *m_eventPtr; const char *m_eventEndPtr; const char *m_positionPtr; OPEN_INTERNAL_ENTITY *m_openInternalEntities; int m_defaultExpandInternalEntities; int m_tagLevel; ENTITY *m_declEntity; const XML_Char *m_declNotationName; const XML_Char *m_declNotationPublicId; ELEMENT_TYPE *m_declElementType; ATTRIBUTE_ID *m_declAttributeId; char m_declAttributeIsCdata; char m_declAttributeIsId; DTD m_dtd; const XML_Char *m_curBase; TAG *m_tagStack; TAG *m_freeTagList; BINDING *m_inheritedBindings; BINDING *m_freeBindingList; int m_attsSize; int m_nSpecifiedAtts; int m_idAttIndex; ATTRIBUTE *m_atts; POSITION m_position; STRING_POOL m_tempPool; STRING_POOL m_temp2Pool; char *m_groupConnector; unsigned m_groupSize; int m_hadExternalDoctype; XML_Char m_namespaceSeparator; #ifdef XML_DTD enum XML_ParamEntityParsing m_paramEntityParsing; XML_Parser m_parentParser; #endif } Parser; #define userData (((Parser *)parser)->m_userData) #define handlerArg (((Parser *)parser)->m_handlerArg) #define startElementHandler (((Parser *)parser)->m_startElementHandler) #define endElementHandler (((Parser *)parser)->m_endElementHandler) #define characterDataHandler (((Parser *)parser)->m_characterDataHandler) #define processingInstructionHandler (((Parser *)parser)->m_processingInstructionHandler) #define commentHandler (((Parser *)parser)->m_commentHandler) #define startCdataSectionHandler (((Parser *)parser)->m_startCdataSectionHandler) #define endCdataSectionHandler (((Parser *)parser)->m_endCdataSectionHandler) #define defaultHandler (((Parser *)parser)->m_defaultHandler) #define startDoctypeDeclHandler (((Parser *)parser)->m_startDoctypeDeclHandler) #define endDoctypeDeclHandler (((Parser *)parser)->m_endDoctypeDeclHandler) #define unparsedEntityDeclHandler (((Parser *)parser)->m_unparsedEntityDeclHandler) #define notationDeclHandler (((Parser *)parser)->m_notationDeclHandler) #define externalParsedEntityDeclHandler (((Parser *)parser)->m_externalParsedEntityDeclHandler) #define internalParsedEntityDeclHandler (((Parser *)parser)->m_internalParsedEntityDeclHandler) #define startNamespaceDeclHandler (((Parser *)parser)->m_startNamespaceDeclHandler) #define endNamespaceDeclHandler (((Parser *)parser)->m_endNamespaceDeclHandler) #define notStandaloneHandler (((Parser *)parser)->m_notStandaloneHandler) #define externalEntityRefHandler (((Parser *)parser)->m_externalEntityRefHandler) #define externalEntityRefHandlerArg (((Parser *)parser)->m_externalEntityRefHandlerArg) #define unknownEncodingHandler (((Parser *)parser)->m_unknownEncodingHandler) #define encoding (((Parser *)parser)->m_encoding) #define initEncoding (((Parser *)parser)->m_initEncoding) #define internalEncoding (((Parser *)parser)->m_internalEncoding) #define unknownEncodingMem (((Parser *)parser)->m_unknownEncodingMem) #define unknownEncodingData (((Parser *)parser)->m_unknownEncodingData) #define unknownEncodingHandlerData \ (((Parser *)parser)->m_unknownEncodingHandlerData) #define unknownEncodingRelease (((Parser *)parser)->m_unknownEncodingRelease) #define protocolEncodingName (((Parser *)parser)->m_protocolEncodingName) #define ns (((Parser *)parser)->m_ns) #define prologState (((Parser *)parser)->m_prologState) #define processor (((Parser *)parser)->m_processor) #define errorCode (((Parser *)parser)->m_errorCode) #define eventPtr (((Parser *)parser)->m_eventPtr) #define eventEndPtr (((Parser *)parser)->m_eventEndPtr) #define positionPtr (((Parser *)parser)->m_positionPtr) #define position (((Parser *)parser)->m_position) #define openInternalEntities (((Parser *)parser)->m_openInternalEntities) #define defaultExpandInternalEntities (((Parser *)parser)->m_defaultExpandInternalEntities) #define tagLevel (((Parser *)parser)->m_tagLevel) #define buffer (((Parser *)parser)->m_buffer) #define bufferPtr (((Parser *)parser)->m_bufferPtr) #define bufferEnd (((Parser *)parser)->m_bufferEnd) #define parseEndByteIndex (((Parser *)parser)->m_parseEndByteIndex) #define parseEndPtr (((Parser *)parser)->m_parseEndPtr) #define bufferLim (((Parser *)parser)->m_bufferLim) #define dataBuf (((Parser *)parser)->m_dataBuf) #define dataBufEnd (((Parser *)parser)->m_dataBufEnd) #define dtd (((Parser *)parser)->m_dtd) #define curBase (((Parser *)parser)->m_curBase) #define declEntity (((Parser *)parser)->m_declEntity) #define declNotationName (((Parser *)parser)->m_declNotationName) #define declNotationPublicId (((Parser *)parser)->m_declNotationPublicId) #define declElementType (((Parser *)parser)->m_declElementType) #define declAttributeId (((Parser *)parser)->m_declAttributeId) #define declAttributeIsCdata (((Parser *)parser)->m_declAttributeIsCdata) #define declAttributeIsId (((Parser *)parser)->m_declAttributeIsId) #define freeTagList (((Parser *)parser)->m_freeTagList) #define freeBindingList (((Parser *)parser)->m_freeBindingList) #define inheritedBindings (((Parser *)parser)->m_inheritedBindings) #define tagStack (((Parser *)parser)->m_tagStack) #define atts (((Parser *)parser)->m_atts) #define attsSize (((Parser *)parser)->m_attsSize) #define nSpecifiedAtts (((Parser *)parser)->m_nSpecifiedAtts) #define idAttIndex (((Parser *)parser)->m_idAttIndex) #define tempPool (((Parser *)parser)->m_tempPool) #define temp2Pool (((Parser *)parser)->m_temp2Pool) #define groupConnector (((Parser *)parser)->m_groupConnector) #define groupSize (((Parser *)parser)->m_groupSize) #define hadExternalDoctype (((Parser *)parser)->m_hadExternalDoctype) #define namespaceSeparator (((Parser *)parser)->m_namespaceSeparator) #ifdef XML_DTD #define parentParser (((Parser *)parser)->m_parentParser) #define paramEntityParsing (((Parser *)parser)->m_paramEntityParsing) #endif /* XML_DTD */ #ifdef _MSC_VER #ifdef _DEBUG Parser *asParser(XML_Parser parser) { return parser; } #endif #endif XML_Parser XML_ParserCreate(const XML_Char *encodingName) { XML_Parser parser = malloc(sizeof(Parser)); if (!parser) return parser; processor = prologInitProcessor; XmlPrologStateInit(&prologState); userData = 0; handlerArg = 0; startElementHandler = 0; endElementHandler = 0; characterDataHandler = 0; processingInstructionHandler = 0; commentHandler = 0; startCdataSectionHandler = 0; endCdataSectionHandler = 0; defaultHandler = 0; startDoctypeDeclHandler = 0; endDoctypeDeclHandler = 0; unparsedEntityDeclHandler = 0; notationDeclHandler = 0; externalParsedEntityDeclHandler = 0; internalParsedEntityDeclHandler = 0; startNamespaceDeclHandler = 0; endNamespaceDeclHandler = 0; notStandaloneHandler = 0; externalEntityRefHandler = 0; externalEntityRefHandlerArg = parser; unknownEncodingHandler = 0; buffer = 0; bufferPtr = 0; bufferEnd = 0; parseEndByteIndex = 0; parseEndPtr = 0; bufferLim = 0; declElementType = 0; declAttributeId = 0; declEntity = 0; declNotationName = 0; declNotationPublicId = 0; memset(&position, 0, sizeof(POSITION)); errorCode = XML_ERROR_NONE; eventPtr = 0; eventEndPtr = 0; positionPtr = 0; openInternalEntities = 0; tagLevel = 0; tagStack = 0; freeTagList = 0; freeBindingList = 0; inheritedBindings = 0; attsSize = INIT_ATTS_SIZE; atts = malloc(attsSize * sizeof(ATTRIBUTE)); nSpecifiedAtts = 0; dataBuf = malloc(INIT_DATA_BUF_SIZE * sizeof(XML_Char)); groupSize = 0; groupConnector = 0; hadExternalDoctype = 0; unknownEncodingMem = 0; unknownEncodingRelease = 0; unknownEncodingData = 0; unknownEncodingHandlerData = 0; namespaceSeparator = '!'; #ifdef XML_DTD parentParser = 0; paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER; #endif ns = 0; poolInit(&tempPool); poolInit(&temp2Pool); protocolEncodingName = encodingName ? poolCopyString(&tempPool, encodingName) : 0; curBase = 0; if (!dtdInit(&dtd) || !atts || !dataBuf || (encodingName && !protocolEncodingName)) { XML_ParserFree(parser); return 0; } dataBufEnd = dataBuf + INIT_DATA_BUF_SIZE; XmlInitEncoding(&initEncoding, &encoding, 0); internalEncoding = XmlGetInternalEncoding(); return parser; } XML_Parser XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep) { static const XML_Char implicitContext[] = { XML_T('x'), XML_T('m'), XML_T('l'), XML_T('='), XML_T('h'), XML_T('t'), XML_T('t'), XML_T('p'), XML_T(':'), XML_T('/'), XML_T('/'), XML_T('w'), XML_T('w'), XML_T('w'), XML_T('.'), XML_T('w'), XML_T('3'), XML_T('.'), XML_T('o'), XML_T('r'), XML_T('g'), XML_T('/'), XML_T('X'), XML_T('M'), XML_T('L'), XML_T('/'), XML_T('1'), XML_T('9'), XML_T('9'), XML_T('8'), XML_T('/'), XML_T('n'), XML_T('a'), XML_T('m'), XML_T('e'), XML_T('s'), XML_T('p'), XML_T('a'), XML_T('c'), XML_T('e'), XML_T('\0') }; XML_Parser parser = XML_ParserCreate(encodingName); if (parser) { XmlInitEncodingNS(&initEncoding, &encoding, 0); ns = 1; internalEncoding = XmlGetInternalEncodingNS(); namespaceSeparator = nsSep; } if (!setContext(parser, implicitContext)) { XML_ParserFree(parser); return 0; } return parser; } int XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName) { if (!encodingName) protocolEncodingName = 0; else { protocolEncodingName = poolCopyString(&tempPool, encodingName); if (!protocolEncodingName) return 0; } return 1; } XML_Parser XML_ExternalEntityParserCreate(XML_Parser oldParser, const XML_Char *context, const XML_Char *encodingName) { XML_Parser parser = oldParser; DTD *oldDtd = &dtd; XML_StartElementHandler oldStartElementHandler = startElementHandler; XML_EndElementHandler oldEndElementHandler = endElementHandler; XML_CharacterDataHandler oldCharacterDataHandler = characterDataHandler; XML_ProcessingInstructionHandler oldProcessingInstructionHandler = processingInstructionHandler; XML_CommentHandler oldCommentHandler = commentHandler; XML_StartCdataSectionHandler oldStartCdataSectionHandler = startCdataSectionHandler; XML_EndCdataSectionHandler oldEndCdataSectionHandler = endCdataSectionHandler; XML_DefaultHandler oldDefaultHandler = defaultHandler; XML_UnparsedEntityDeclHandler oldUnparsedEntityDeclHandler = unparsedEntityDeclHandler; XML_NotationDeclHandler oldNotationDeclHandler = notationDeclHandler; XML_ExternalParsedEntityDeclHandler oldExternalParsedEntityDeclHandler = externalParsedEntityDeclHandler; XML_InternalParsedEntityDeclHandler oldInternalParsedEntityDeclHandler = internalParsedEntityDeclHandler; XML_StartNamespaceDeclHandler oldStartNamespaceDeclHandler = startNamespaceDeclHandler; XML_EndNamespaceDeclHandler oldEndNamespaceDeclHandler = endNamespaceDeclHandler; XML_NotStandaloneHandler oldNotStandaloneHandler = notStandaloneHandler; XML_ExternalEntityRefHandler oldExternalEntityRefHandler = externalEntityRefHandler; XML_UnknownEncodingHandler oldUnknownEncodingHandler = unknownEncodingHandler; void *oldUserData = userData; void *oldHandlerArg = handlerArg; int oldDefaultExpandInternalEntities = defaultExpandInternalEntities; void *oldExternalEntityRefHandlerArg = externalEntityRefHandlerArg; #ifdef XML_DTD int oldParamEntityParsing = paramEntityParsing; #endif parser = (ns ? XML_ParserCreateNS(encodingName, namespaceSeparator) : XML_ParserCreate(encodingName)); if (!parser) return 0; startElementHandler = oldStartElementHandler; endElementHandler = oldEndElementHandler; characterDataHandler = oldCharacterDataHandler; processingInstructionHandler = oldProcessingInstructionHandler; commentHandler = oldCommentHandler; startCdataSectionHandler = oldStartCdataSectionHandler; endCdataSectionHandler = oldEndCdataSectionHandler; defaultHandler = oldDefaultHandler; unparsedEntityDeclHandler = oldUnparsedEntityDeclHandler; notationDeclHandler = oldNotationDeclHandler; externalParsedEntityDeclHandler = oldExternalParsedEntityDeclHandler; internalParsedEntityDeclHandler = oldInternalParsedEntityDeclHandler; startNamespaceDeclHandler = oldStartNamespaceDeclHandler; endNamespaceDeclHandler = oldEndNamespaceDeclHandler; notStandaloneHandler = oldNotStandaloneHandler; externalEntityRefHandler = oldExternalEntityRefHandler; unknownEncodingHandler = oldUnknownEncodingHandler; userData = oldUserData; if (oldUserData == oldHandlerArg) handlerArg = userData; else handlerArg = parser; if (oldExternalEntityRefHandlerArg != oldParser) externalEntityRefHandlerArg = oldExternalEntityRefHandlerArg; defaultExpandInternalEntities = oldDefaultExpandInternalEntities; #ifdef XML_DTD paramEntityParsing = oldParamEntityParsing; if (context) { #endif /* XML_DTD */ if (!dtdCopy(&dtd, oldDtd) || !setContext(parser, context)) { XML_ParserFree(parser); return 0; } processor = externalEntityInitProcessor; #ifdef XML_DTD } else { dtdSwap(&dtd, oldDtd); parentParser = oldParser; XmlPrologStateInitExternalEntity(&prologState); dtd.complete = 1; hadExternalDoctype = 1; } #endif /* XML_DTD */ return parser; } static void destroyBindings(BINDING *bindings) { for (;;) { BINDING *b = bindings; if (!b) break; bindings = b->nextTagBinding; free(b->uri); free(b); } } void XML_ParserFree(XML_Parser parser) { for (;;) { TAG *p; if (tagStack == 0) { if (freeTagList == 0) break; tagStack = freeTagList; freeTagList = 0; } p = tagStack; tagStack = tagStack->parent; free(p->buf); destroyBindings(p->bindings); free(p); } destroyBindings(freeBindingList); destroyBindings(inheritedBindings); poolDestroy(&tempPool); poolDestroy(&temp2Pool); #ifdef XML_DTD if (parentParser) { if (hadExternalDoctype) dtd.complete = 0; dtdSwap(&dtd, &((Parser *)parentParser)->m_dtd); } #endif /* XML_DTD */ dtdDestroy(&dtd); free((void *)atts); free(groupConnector); free(buffer); free(dataBuf); free(unknownEncodingMem); if (unknownEncodingRelease) unknownEncodingRelease(unknownEncodingData); free(parser); } void XML_UseParserAsHandlerArg(XML_Parser parser) { handlerArg = parser; } void XML_SetUserData(XML_Parser parser, void *p) { if (handlerArg == userData) handlerArg = userData = p; else userData = p; } int XML_SetBase(XML_Parser parser, const XML_Char *p) { if (p) { p = poolCopyString(&dtd.pool, p); if (!p) return 0; curBase = p; } else curBase = 0; return 1; } const XML_Char *XML_GetBase(XML_Parser parser) { return curBase; } int XML_GetSpecifiedAttributeCount(XML_Parser parser) { return nSpecifiedAtts; } int XML_GetIdAttributeIndex(XML_Parser parser) { return idAttIndex; } void XML_SetElementHandler(XML_Parser parser, XML_StartElementHandler start, XML_EndElementHandler end) { startElementHandler = start; endElementHandler = end; } void XML_SetCharacterDataHandler(XML_Parser parser, XML_CharacterDataHandler handler) { characterDataHandler = handler; } void XML_SetProcessingInstructionHandler(XML_Parser parser, XML_ProcessingInstructionHandler handler) { processingInstructionHandler = handler; } void XML_SetCommentHandler(XML_Parser parser, XML_CommentHandler handler) { commentHandler = handler; } void XML_SetCdataSectionHandler(XML_Parser parser, XML_StartCdataSectionHandler start, XML_EndCdataSectionHandler end) { startCdataSectionHandler = start; endCdataSectionHandler = end; } void XML_SetDefaultHandler(XML_Parser parser, XML_DefaultHandler handler) { defaultHandler = handler; defaultExpandInternalEntities = 0; } void XML_SetDefaultHandlerExpand(XML_Parser parser, XML_DefaultHandler handler) { defaultHandler = handler; defaultExpandInternalEntities = 1; } void XML_SetDoctypeDeclHandler(XML_Parser parser, XML_StartDoctypeDeclHandler start, XML_EndDoctypeDeclHandler end) { startDoctypeDeclHandler = start; endDoctypeDeclHandler = end; } void XML_SetUnparsedEntityDeclHandler(XML_Parser parser, XML_UnparsedEntityDeclHandler handler) { unparsedEntityDeclHandler = handler; } void XML_SetExternalParsedEntityDeclHandler(XML_Parser parser, XML_ExternalParsedEntityDeclHandler handler) { externalParsedEntityDeclHandler = handler; } void XML_SetInternalParsedEntityDeclHandler(XML_Parser parser, XML_InternalParsedEntityDeclHandler handler) { internalParsedEntityDeclHandler = handler; } void XML_SetNotationDeclHandler(XML_Parser parser, XML_NotationDeclHandler handler) { notationDeclHandler = handler; } void XML_SetNamespaceDeclHandler(XML_Parser parser, XML_StartNamespaceDeclHandler start, XML_EndNamespaceDeclHandler end) { startNamespaceDeclHandler = start; endNamespaceDeclHandler = end; } void XML_SetNotStandaloneHandler(XML_Parser parser, XML_NotStandaloneHandler handler) { notStandaloneHandler = handler; } void XML_SetExternalEntityRefHandler(XML_Parser parser, XML_ExternalEntityRefHandler handler) { externalEntityRefHandler = handler; } void XML_SetExternalEntityRefHandlerArg(XML_Parser parser, void *arg) { if (arg) externalEntityRefHandlerArg = arg; else externalEntityRefHandlerArg = parser; } void XML_SetUnknownEncodingHandler(XML_Parser parser, XML_UnknownEncodingHandler handler, void *data) { unknownEncodingHandler = handler; unknownEncodingHandlerData = data; } int XML_SetParamEntityParsing(XML_Parser parser, enum XML_ParamEntityParsing parsing) { #ifdef XML_DTD paramEntityParsing = parsing; return 1; #else return parsing == XML_PARAM_ENTITY_PARSING_NEVER; #endif } int XML_Parse(XML_Parser parser, const char *s, int len, int isFinal) { if (len == 0) { if (!isFinal) return 1; positionPtr = bufferPtr; errorCode = processor(parser, bufferPtr, parseEndPtr = bufferEnd, 0); if (errorCode == XML_ERROR_NONE) return 1; eventEndPtr = eventPtr; processor = errorProcessor; return 0; } else if (bufferPtr == bufferEnd) { const char *end; int nLeftOver; parseEndByteIndex += len; positionPtr = s; if (isFinal) { errorCode = processor(parser, s, parseEndPtr = s + len, 0); if (errorCode == XML_ERROR_NONE) return 1; eventEndPtr = eventPtr; processor = errorProcessor; return 0; } errorCode = processor(parser, s, parseEndPtr = s + len, &end); if (errorCode != XML_ERROR_NONE) { eventEndPtr = eventPtr; processor = errorProcessor; return 0; } XmlUpdatePosition(encoding, positionPtr, end, &position); nLeftOver = s + len - end; if (nLeftOver) { if (buffer == 0 || nLeftOver > bufferLim - buffer) { /* FIXME avoid integer overflow */ buffer = buffer == 0 ? malloc(len * 2) : realloc(buffer, len * 2); /* FIXME storage leak if realloc fails */ if (!buffer) { errorCode = XML_ERROR_NO_MEMORY; eventPtr = eventEndPtr = 0; processor = errorProcessor; return 0; } bufferLim = buffer + len * 2; } memcpy(buffer, end, nLeftOver); bufferPtr = buffer; bufferEnd = buffer + nLeftOver; } return 1; } else { memcpy(XML_GetBuffer(parser, len), s, len); return XML_ParseBuffer(parser, len, isFinal); } } int XML_ParseBuffer(XML_Parser parser, int len, int isFinal) { const char *start = bufferPtr; positionPtr = start; bufferEnd += len; parseEndByteIndex += len; errorCode = processor(parser, start, parseEndPtr = bufferEnd, isFinal ? (const char **)0 : &bufferPtr); if (errorCode == XML_ERROR_NONE) { if (!isFinal) XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position); return 1; } else { eventEndPtr = eventPtr; processor = errorProcessor; return 0; } } void *XML_GetBuffer(XML_Parser parser, int len) { if (len > bufferLim - bufferEnd) { /* FIXME avoid integer overflow */ int neededSize = len + (bufferEnd - bufferPtr); if (neededSize <= bufferLim - buffer) { memmove(buffer, bufferPtr, bufferEnd - bufferPtr); bufferEnd = buffer + (bufferEnd - bufferPtr); bufferPtr = buffer; } else { char *newBuf; int bufferSize = bufferLim - bufferPtr; if (bufferSize == 0) bufferSize = INIT_BUFFER_SIZE; do { bufferSize *= 2; } while (bufferSize < neededSize); newBuf = malloc(bufferSize); if (newBuf == 0) { errorCode = XML_ERROR_NO_MEMORY; return 0; } bufferLim = newBuf + bufferSize; if (bufferPtr) { memcpy(newBuf, bufferPtr, bufferEnd - bufferPtr); free(buffer); } bufferEnd = newBuf + (bufferEnd - bufferPtr); bufferPtr = buffer = newBuf; } } return bufferEnd; } enum XML_Error XML_GetErrorCode(XML_Parser parser) { return errorCode; } long XML_GetCurrentByteIndex(XML_Parser parser) { if (eventPtr) return parseEndByteIndex - (parseEndPtr - eventPtr); return -1; } int XML_GetCurrentByteCount(XML_Parser parser) { if (eventEndPtr && eventPtr) return eventEndPtr - eventPtr; return 0; } int XML_GetCurrentLineNumber(XML_Parser parser) { if (eventPtr) { XmlUpdatePosition(encoding, positionPtr, eventPtr, &position); positionPtr = eventPtr; } return position.lineNumber + 1; } int XML_GetCurrentColumnNumber(XML_Parser parser) { if (eventPtr) { XmlUpdatePosition(encoding, positionPtr, eventPtr, &position); positionPtr = eventPtr; } return position.columnNumber; } void XML_DefaultCurrent(XML_Parser parser) { if (defaultHandler) { if (openInternalEntities) reportDefault(parser, internalEncoding, openInternalEntities->internalEventPtr, openInternalEntities->internalEventEndPtr); else reportDefault(parser, encoding, eventPtr, eventEndPtr); } } const XML_LChar *XML_ErrorString(int code) { static const XML_LChar *message[] = { 0, XML_T("out of memory"), XML_T("syntax error"), XML_T("no element found"), XML_T("not well-formed"), XML_T("unclosed token"), XML_T("unclosed token"), XML_T("mismatched tag"), XML_T("duplicate attribute"), XML_T("junk after document element"), XML_T("illegal parameter entity reference"), XML_T("undefined entity"), XML_T("recursive entity reference"), XML_T("asynchronous entity"), XML_T("reference to invalid character number"), XML_T("reference to binary entity"), XML_T("reference to external entity in attribute"), XML_T("xml processing instruction not at start of external entity"), XML_T("unknown encoding"), XML_T("encoding specified in XML declaration is incorrect"), XML_T("unclosed CDATA section"), XML_T("error in processing external entity reference"), XML_T("document is not standalone") }; if (code > 0 && code < sizeof(message)/sizeof(message[0])) return message[code]; return 0; } static enum XML_Error contentProcessor(XML_Parser parser, const char *start, const char *end, const char **endPtr) { return doContent(parser, 0, encoding, start, end, endPtr); } static enum XML_Error externalEntityInitProcessor(XML_Parser parser, const char *start, const char *end, const char **endPtr) { enum XML_Error result = initializeEncoding(parser); if (result != XML_ERROR_NONE) return result; processor = externalEntityInitProcessor2; return externalEntityInitProcessor2(parser, start, end, endPtr); } static enum XML_Error externalEntityInitProcessor2(XML_Parser parser, const char *start, const char *end, const char **endPtr) { const char *next; int tok = XmlContentTok(encoding, start, end, &next); switch (tok) { case XML_TOK_BOM: start = next; break; case XML_TOK_PARTIAL: if (endPtr) { *endPtr = start; return XML_ERROR_NONE; } eventPtr = start; return XML_ERROR_UNCLOSED_TOKEN; case XML_TOK_PARTIAL_CHAR: if (endPtr) { *endPtr = start; return XML_ERROR_NONE; } eventPtr = start; return XML_ERROR_PARTIAL_CHAR; } processor = externalEntityInitProcessor3; return externalEntityInitProcessor3(parser, start, end, endPtr); } static enum XML_Error externalEntityInitProcessor3(XML_Parser parser, const char *start, const char *end, const char **endPtr) { const char *next; int tok = XmlContentTok(encoding, start, end, &next); switch (tok) { case XML_TOK_XML_DECL: { enum XML_Error result = processXmlDecl(parser, 1, start, next); if (result != XML_ERROR_NONE) return result; start = next; } break; case XML_TOK_PARTIAL: if (endPtr) { *endPtr = start; return XML_ERROR_NONE; } eventPtr = start; return XML_ERROR_UNCLOSED_TOKEN; case XML_TOK_PARTIAL_CHAR: if (endPtr) { *endPtr = start; return XML_ERROR_NONE; } eventPtr = start; return XML_ERROR_PARTIAL_CHAR; } processor = externalEntityContentProcessor; tagLevel = 1; return doContent(parser, 1, encoding, start, end, endPtr); } static enum XML_Error externalEntityContentProcessor(XML_Parser parser, const char *start, const char *end, const char **endPtr) { return doContent(parser, 1, encoding, start, end, endPtr); } static enum XML_Error doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc, const char *s, const char *end, const char **nextPtr) { const char **eventPP; const char **eventEndPP; if (enc == encoding) { eventPP = &eventPtr; eventEndPP = &eventEndPtr; } else { eventPP = &(openInternalEntities->internalEventPtr); eventEndPP = &(openInternalEntities->internalEventEndPtr); } *eventPP = s; for (;;) { const char *next = s; /* XmlContentTok doesn't always set the last arg */ int tok = XmlContentTok(enc, s, end, &next); *eventEndPP = next; switch (tok) { case XML_TOK_TRAILING_CR: if (nextPtr) { *nextPtr = s; return XML_ERROR_NONE; } *eventEndPP = end; if (characterDataHandler) { XML_Char c = 0xA; characterDataHandler(handlerArg, &c, 1); } else if (defaultHandler) reportDefault(parser, enc, s, end); if (startTagLevel == 0) return XML_ERROR_NO_ELEMENTS; if (tagLevel != startTagLevel) return XML_ERROR_ASYNC_ENTITY; return XML_ERROR_NONE; case XML_TOK_NONE: if (nextPtr) { *nextPtr = s; return XML_ERROR_NONE; } if (startTagLevel > 0) { if (tagLevel != startTagLevel) return XML_ERROR_ASYNC_ENTITY; return XML_ERROR_NONE; } return XML_ERROR_NO_ELEMENTS; case XML_TOK_INVALID: *eventPP = next; return XML_ERROR_INVALID_TOKEN; case XML_TOK_PARTIAL: if (nextPtr) { *nextPtr = s; return XML_ERROR_NONE; } return XML_ERROR_UNCLOSED_TOKEN; case XML_TOK_PARTIAL_CHAR: if (nextPtr) { *nextPtr = s; return XML_ERROR_NONE; } return XML_ERROR_PARTIAL_CHAR; case XML_TOK_ENTITY_REF: { const XML_Char *name; ENTITY *entity; XML_Char ch = XmlPredefinedEntityName(enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar); if (ch) { if (characterDataHandler) characterDataHandler(handlerArg, &ch, 1); else if (defaultHandler) reportDefault(parser, enc, s, next); break; } name = poolStoreString(&dtd.pool, enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar); if (!name) return XML_ERROR_NO_MEMORY; entity = (ENTITY *)lookup(&dtd.generalEntities, name, 0); poolDiscard(&dtd.pool); if (!entity) { if (dtd.complete || dtd.standalone) return XML_ERROR_UNDEFINED_ENTITY; if (defaultHandler) reportDefault(parser, enc, s, next); break; } if (entity->open) return XML_ERROR_RECURSIVE_ENTITY_REF; if (entity->notation) return XML_ERROR_BINARY_ENTITY_REF; if (entity) { if (entity->textPtr) { enum XML_Error result; OPEN_INTERNAL_ENTITY openEntity; if (defaultHandler && !defaultExpandInternalEntities) { reportDefault(parser, enc, s, next); break; } entity->open = 1; openEntity.next = openInternalEntities; openInternalEntities = &openEntity; openEntity.entity = entity; openEntity.internalEventPtr = 0; openEntity.internalEventEndPtr = 0; result = doContent(parser, tagLevel, internalEncoding, (char *)entity->textPtr, (char *)(entity->textPtr + entity->textLen), 0); entity->open = 0; openInternalEntities = openEntity.next; if (result) return result; } else if (externalEntityRefHandler) { const XML_Char *context; entity->open = 1; context = getContext(parser); entity->open = 0; if (!context) return XML_ERROR_NO_MEMORY; if (!externalEntityRefHandler(externalEntityRefHandlerArg, context, entity->base, entity->systemId, entity->publicId)) return XML_ERROR_EXTERNAL_ENTITY_HANDLING; poolDiscard(&tempPool); } else if (defaultHandler) reportDefault(parser, enc, s, next); } break; } case XML_TOK_START_TAG_WITH_ATTS: if (!startElementHandler) { enum XML_Error result = storeAtts(parser, enc, s, 0, 0); if (result) return result; } /* fall through */ case XML_TOK_START_TAG_NO_ATTS: { TAG *tag; if (freeTagList) { tag = freeTagList; freeTagList = freeTagList->parent; } else { tag = malloc(sizeof(TAG)); if (!tag) return XML_ERROR_NO_MEMORY; tag->buf = malloc(INIT_TAG_BUF_SIZE); if (!tag->buf) return XML_ERROR_NO_MEMORY; tag->bufEnd = tag->buf + INIT_TAG_BUF_SIZE; } tag->bindings = 0; tag->parent = tagStack; tagStack = tag; tag->name.localPart = 0; tag->rawName = s + enc->minBytesPerChar; tag->rawNameLength = XmlNameLength(enc, tag->rawName); if (nextPtr) { /* Need to guarantee that: tag->buf + ROUND_UP(tag->rawNameLength, sizeof(XML_Char)) <= tag->bufEnd - sizeof(XML_Char) */ if (tag->rawNameLength + (int)(sizeof(XML_Char) - 1) + (int)sizeof(XML_Char) > tag->bufEnd - tag->buf) { int bufSize = tag->rawNameLength * 4; bufSize = ROUND_UP(bufSize, sizeof(XML_Char)); tag->buf = realloc(tag->buf, bufSize); if (!tag->buf) return XML_ERROR_NO_MEMORY; tag->bufEnd = tag->buf + bufSize; } memcpy(tag->buf, tag->rawName, tag->rawNameLength); tag->rawName = tag->buf; } ++tagLevel; if (startElementHandler) { enum XML_Error result; XML_Char *toPtr; for (;;) { const char *rawNameEnd = tag->rawName + tag->rawNameLength; const char *fromPtr = tag->rawName; int bufSize; if (nextPtr) toPtr = (XML_Char *)(tag->buf + ROUND_UP(tag->rawNameLength, sizeof(XML_Char))); else toPtr = (XML_Char *)tag->buf; tag->name.str = toPtr; XmlConvert(enc, &fromPtr, rawNameEnd, (ICHAR **)&toPtr, (ICHAR *)tag->bufEnd - 1); if (fromPtr == rawNameEnd) break; bufSize = (tag->bufEnd - tag->buf) << 1; tag->buf = realloc(tag->buf, bufSize); if (!tag->buf) return XML_ERROR_NO_MEMORY; tag->bufEnd = tag->buf + bufSize; if (nextPtr) tag->rawName = tag->buf; } *toPtr = XML_T('\0'); result = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings)); if (result) return result; startElementHandler(handlerArg, tag->name.str, (const XML_Char **)atts); poolClear(&tempPool); } else { tag->name.str = 0; if (defaultHandler) reportDefault(parser, enc, s, next); } break; } case XML_TOK_EMPTY_ELEMENT_WITH_ATTS: if (!startElementHandler) { enum XML_Error result = storeAtts(parser, enc, s, 0, 0); if (result) return result; } /* fall through */ case XML_TOK_EMPTY_ELEMENT_NO_ATTS: if (startElementHandler || endElementHandler) { const char *rawName = s + enc->minBytesPerChar; enum XML_Error result; BINDING *bindings = 0; TAG_NAME name; name.str = poolStoreString(&tempPool, enc, rawName, rawName + XmlNameLength(enc, rawName)); if (!name.str) return XML_ERROR_NO_MEMORY; poolFinish(&tempPool); result = storeAtts(parser, enc, s, &name, &bindings); if (result) return result; poolFinish(&tempPool); if (startElementHandler) startElementHandler(handlerArg, name.str, (const XML_Char **)atts); if (endElementHandler) { if (startElementHandler) *eventPP = *eventEndPP; endElementHandler(handlerArg, name.str); } poolClear(&tempPool); while (bindings) { BINDING *b = bindings; if (endNamespaceDeclHandler) endNamespaceDeclHandler(handlerArg, b->prefix->name); bindings = bindings->nextTagBinding; b->nextTagBinding = freeBindingList; freeBindingList = b; b->prefix->binding = b->prevPrefixBinding; } } else if (defaultHandler) reportDefault(parser, enc, s, next); if (tagLevel == 0) return epilogProcessor(parser, next, end, nextPtr); break; case XML_TOK_END_TAG: if (tagLevel == startTagLevel) return XML_ERROR_ASYNC_ENTITY; else { int len; const char *rawName; TAG *tag = tagStack; tagStack = tag->parent; tag->parent = freeTagList; freeTagList = tag; rawName = s + enc->minBytesPerChar*2; len = XmlNameLength(enc, rawName); if (len != tag->rawNameLength || memcmp(tag->rawName, rawName, len) != 0) { *eventPP = rawName; return XML_ERROR_TAG_MISMATCH; } --tagLevel; if (endElementHandler && tag->name.str) { if (tag->name.localPart) { XML_Char *to = (XML_Char *)tag->name.str + tag->name.uriLen; const XML_Char *from = tag->name.localPart; while ((*to++ = *from++) != 0) ; } endElementHandler(handlerArg, tag->name.str); } else if (defaultHandler) reportDefault(parser, enc, s, next); while (tag->bindings) { BINDING *b = tag->bindings; if (endNamespaceDeclHandler) endNamespaceDeclHandler(handlerArg, b->prefix->name); tag->bindings = tag->bindings->nextTagBinding; b->nextTagBinding = freeBindingList; freeBindingList = b; b->prefix->binding = b->prevPrefixBinding; } if (tagLevel == 0) return epilogProcessor(parser, next, end, nextPtr); } break; case XML_TOK_CHAR_REF: { int n = XmlCharRefNumber(enc, s); if (n < 0) return XML_ERROR_BAD_CHAR_REF; if (characterDataHandler) { XML_Char buf[XML_ENCODE_MAX]; characterDataHandler(handlerArg, buf, XmlEncode(n, (ICHAR *)buf)); } else if (defaultHandler) reportDefault(parser, enc, s, next); } break; case XML_TOK_XML_DECL: return XML_ERROR_MISPLACED_XML_PI; case XML_TOK_DATA_NEWLINE: if (characterDataHandler) { XML_Char c = 0xA; characterDataHandler(handlerArg, &c, 1); } else if (defaultHandler) reportDefault(parser, enc, s, next); break; case XML_TOK_CDATA_SECT_OPEN: { enum XML_Error result; if (startCdataSectionHandler) startCdataSectionHandler(handlerArg); #if 0 /* Suppose you doing a transformation on a document that involves changing only the character data. You set up a defaultHandler and a characterDataHandler. The defaultHandler simply copies characters through. The characterDataHandler does the transformation and writes the characters out escaping them as necessary. This case will fail to work if we leave out the following two lines (because & and < inside CDATA sections will be incorrectly escaped). However, now we have a start/endCdataSectionHandler, so it seems easier to let the user deal with this. */ else if (characterDataHandler) characterDataHandler(handlerArg, dataBuf, 0); #endif else if (defaultHandler) reportDefault(parser, enc, s, next); result = doCdataSection(parser, enc, &next, end, nextPtr); if (!next) { processor = cdataSectionProcessor; return result; } } break; case XML_TOK_TRAILING_RSQB: if (nextPtr) { *nextPtr = s; return XML_ERROR_NONE; } if (characterDataHandler) { if (MUST_CONVERT(enc, s)) { ICHAR *dataPtr = (ICHAR *)dataBuf; XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd); characterDataHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf); } else characterDataHandler(handlerArg, (XML_Char *)s, (XML_Char *)end - (XML_Char *)s); } else if (defaultHandler) reportDefault(parser, enc, s, end); if (startTagLevel == 0) { *eventPP = end; return XML_ERROR_NO_ELEMENTS; } if (tagLevel != startTagLevel) { *eventPP = end; return XML_ERROR_ASYNC_ENTITY; } return XML_ERROR_NONE; case XML_TOK_DATA_CHARS: if (characterDataHandler) { if (MUST_CONVERT(enc, s)) { for (;;) { ICHAR *dataPtr = (ICHAR *)dataBuf; XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd); *eventEndPP = s; characterDataHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf); if (s == next) break; *eventPP = s; } } else characterDataHandler(handlerArg, (XML_Char *)s, (XML_Char *)next - (XML_Char *)s); } else if (defaultHandler) reportDefault(parser, enc, s, next); break; case XML_TOK_PI: if (!reportProcessingInstruction(parser, enc, s, next)) return XML_ERROR_NO_MEMORY; break; case XML_TOK_COMMENT: if (!reportComment(parser, enc, s, next)) return XML_ERROR_NO_MEMORY; break; default: if (defaultHandler) reportDefault(parser, enc, s, next); break; } *eventPP = s = next; } /* not reached */ } /* If tagNamePtr is non-null, build a real list of attributes, otherwise just check the attributes for well-formedness. */ static enum XML_Error storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr, TAG_NAME *tagNamePtr, BINDING **bindingsPtr) { ELEMENT_TYPE *elementType = 0; int nDefaultAtts = 0; const XML_Char **appAtts; /* the attribute list to pass to the application */ int attIndex = 0; int i; int n; int nPrefixes = 0; BINDING *binding; const XML_Char *localPart; /* lookup the element type name */ if (tagNamePtr) { elementType = (ELEMENT_TYPE *)lookup(&dtd.elementTypes, tagNamePtr->str, 0); if (!elementType) { tagNamePtr->str = poolCopyString(&dtd.pool, tagNamePtr->str); if (!tagNamePtr->str) return XML_ERROR_NO_MEMORY; elementType = (ELEMENT_TYPE *)lookup(&dtd.elementTypes, tagNamePtr->str, sizeof(ELEMENT_TYPE)); if (!elementType) return XML_ERROR_NO_MEMORY; if (ns && !setElementTypePrefix(parser, elementType)) return XML_ERROR_NO_MEMORY; } nDefaultAtts = elementType->nDefaultAtts; } /* get the attributes from the tokenizer */ n = XmlGetAttributes(enc, attStr, attsSize, atts); if (n + nDefaultAtts > attsSize) { int oldAttsSize = attsSize; attsSize = n + nDefaultAtts + INIT_ATTS_SIZE; atts = realloc((void *)atts, attsSize * sizeof(ATTRIBUTE)); if (!atts) return XML_ERROR_NO_MEMORY; if (n > oldAttsSize) XmlGetAttributes(enc, attStr, n, atts); } appAtts = (const XML_Char **)atts; for (i = 0; i < n; i++) { /* add the name and value to the attribute list */ ATTRIBUTE_ID *attId = getAttributeId(parser, enc, atts[i].name, atts[i].name + XmlNameLength(enc, atts[i].name)); if (!attId) return XML_ERROR_NO_MEMORY; /* detect duplicate attributes */ if ((attId->name)[-1]) { if (enc == encoding) eventPtr = atts[i].name; return XML_ERROR_DUPLICATE_ATTRIBUTE; } (attId->name)[-1] = 1; appAtts[attIndex++] = attId->name; if (!atts[i].normalized) { enum XML_Error result; int isCdata = 1; /* figure out whether declared as other than CDATA */ if (attId->maybeTokenized) { int j; for (j = 0; j < nDefaultAtts; j++) { if (attId == elementType->defaultAtts[j].id) { isCdata = elementType->defaultAtts[j].isCdata; break; } } } /* normalize the attribute value */ result = storeAttributeValue(parser, enc, isCdata, atts[i].valuePtr, atts[i].valueEnd, &tempPool); if (result) return result; if (tagNamePtr) { appAtts[attIndex] = poolStart(&tempPool); poolFinish(&tempPool); } else poolDiscard(&tempPool); } else if (tagNamePtr) { /* the value did not need normalizing */ appAtts[attIndex] = poolStoreString(&tempPool, enc, atts[i].valuePtr, atts[i].valueEnd); if (appAtts[attIndex] == 0) return XML_ERROR_NO_MEMORY; poolFinish(&tempPool); } /* handle prefixed attribute names */ if (attId->prefix && tagNamePtr) { if (attId->xmlns) { /* deal with namespace declarations here */ if (!addBinding(parser, attId->prefix, attId, appAtts[attIndex], bindingsPtr)) return XML_ERROR_NO_MEMORY; --attIndex; } else { /* deal with other prefixed names later */ attIndex++; nPrefixes++; (attId->name)[-1] = 2; } } else attIndex++; } if (tagNamePtr) { int j; nSpecifiedAtts = attIndex; if (elementType->idAtt && (elementType->idAtt->name)[-1]) { for (i = 0; i < attIndex; i += 2) if (appAtts[i] == elementType->idAtt->name) { idAttIndex = i; break; } } else idAttIndex = -1; /* do attribute defaulting */ for (j = 0; j < nDefaultAtts; j++) { const DEFAULT_ATTRIBUTE *da = elementType->defaultAtts + j; if (!(da->id->name)[-1] && da->value) { if (da->id->prefix) { if (da->id->xmlns) { if (!addBinding(parser, da->id->prefix, da->id, da->value, bindingsPtr)) return XML_ERROR_NO_MEMORY; } else { (da->id->name)[-1] = 2; nPrefixes++; appAtts[attIndex++] = da->id->name; appAtts[attIndex++] = da->value; } } else { (da->id->name)[-1] = 1; appAtts[attIndex++] = da->id->name; appAtts[attIndex++] = da->value; } } } appAtts[attIndex] = 0; } i = 0; if (nPrefixes) { /* expand prefixed attribute names */ for (; i < attIndex; i += 2) { if (appAtts[i][-1] == 2) { ATTRIBUTE_ID *id; ((XML_Char *)(appAtts[i]))[-1] = 0; id = (ATTRIBUTE_ID *)lookup(&dtd.attributeIds, appAtts[i], 0); if (id->prefix->binding) { int j; const BINDING *b = id->prefix->binding; const XML_Char *s = appAtts[i]; for (j = 0; j < b->uriLen; j++) { if (!poolAppendChar(&tempPool, b->uri[j])) return XML_ERROR_NO_MEMORY; } while (*s++ != ':') ; do { if (!poolAppendChar(&tempPool, *s)) return XML_ERROR_NO_MEMORY; } while (*s++); appAtts[i] = poolStart(&tempPool); poolFinish(&tempPool); } if (!--nPrefixes) break; } else ((XML_Char *)(appAtts[i]))[-1] = 0; } } /* clear the flags that say whether attributes were specified */ for (; i < attIndex; i += 2) ((XML_Char *)(appAtts[i]))[-1] = 0; if (!tagNamePtr) return XML_ERROR_NONE; for (binding = *bindingsPtr; binding; binding = binding->nextTagBinding) binding->attId->name[-1] = 0; /* expand the element type name */ if (elementType->prefix) { binding = elementType->prefix->binding; if (!binding) return XML_ERROR_NONE; localPart = tagNamePtr->str; while (*localPart++ != XML_T(':')) ; } else if (dtd.defaultPrefix.binding) { binding = dtd.defaultPrefix.binding; localPart = tagNamePtr->str; } else return XML_ERROR_NONE; tagNamePtr->localPart = localPart; tagNamePtr->uriLen = binding->uriLen; for (i = 0; localPart[i++];) ; n = i + binding->uriLen; if (n > binding->uriAlloc) { TAG *p; XML_Char *uri = malloc((n + EXPAND_SPARE) * sizeof(XML_Char)); if (!uri) return XML_ERROR_NO_MEMORY; binding->uriAlloc = n + EXPAND_SPARE; memcpy(uri, binding->uri, binding->uriLen * sizeof(XML_Char)); for (p = tagStack; p; p = p->parent) if (p->name.str == binding->uri) p->name.str = uri; free(binding->uri); binding->uri = uri; } memcpy(binding->uri + binding->uriLen, localPart, i * sizeof(XML_Char)); tagNamePtr->str = binding->uri; return XML_ERROR_NONE; } static int addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, const XML_Char *uri, BINDING **bindingsPtr) { BINDING *b; int len; for (len = 0; uri[len]; len++) ; if (namespaceSeparator) len++; if (freeBindingList) { b = freeBindingList; if (len > b->uriAlloc) { b->uri = realloc(b->uri, sizeof(XML_Char) * (len + EXPAND_SPARE)); if (!b->uri) return 0; b->uriAlloc = len + EXPAND_SPARE; } freeBindingList = b->nextTagBinding; } else { b = malloc(sizeof(BINDING)); if (!b) return 0; b->uri = malloc(sizeof(XML_Char) * (len + EXPAND_SPARE)); if (!b->uri) { free(b); return 0; } b->uriAlloc = len + EXPAND_SPARE; } b->uriLen = len; memcpy(b->uri, uri, len * sizeof(XML_Char)); if (namespaceSeparator) b->uri[len - 1] = namespaceSeparator; b->prefix = prefix; b->attId = attId; b->prevPrefixBinding = prefix->binding; if (*uri == XML_T('\0') && prefix == &dtd.defaultPrefix) prefix->binding = 0; else prefix->binding = b; b->nextTagBinding = *bindingsPtr; *bindingsPtr = b; if (startNamespaceDeclHandler) startNamespaceDeclHandler(handlerArg, prefix->name, prefix->binding ? uri : 0); return 1; } /* The idea here is to avoid using stack for each CDATA section when the whole file is parsed with one call. */ static enum XML_Error cdataSectionProcessor(XML_Parser parser, const char *start, const char *end, const char **endPtr) { enum XML_Error result = doCdataSection(parser, encoding, &start, end, endPtr); if (start) { processor = contentProcessor; return contentProcessor(parser, start, end, endPtr); } return result; } /* startPtr gets set to non-null is the section is closed, and to null if the section is not yet closed. */ static enum XML_Error doCdataSection(XML_Parser parser, const ENCODING *enc, const char **startPtr, const char *end, const char **nextPtr) { const char *s = *startPtr; const char **eventPP; const char **eventEndPP; if (enc == encoding) { eventPP = &eventPtr; *eventPP = s; eventEndPP = &eventEndPtr; } else { eventPP = &(openInternalEntities->internalEventPtr); eventEndPP = &(openInternalEntities->internalEventEndPtr); } *eventPP = s; *startPtr = 0; for (;;) { const char *next; int tok = XmlCdataSectionTok(enc, s, end, &next); *eventEndPP = next; switch (tok) { case XML_TOK_CDATA_SECT_CLOSE: if (endCdataSectionHandler) endCdataSectionHandler(handlerArg); #if 0 /* see comment under XML_TOK_CDATA_SECT_OPEN */ else if (characterDataHandler) characterDataHandler(handlerArg, dataBuf, 0); #endif else if (defaultHandler) reportDefault(parser, enc, s, next); *startPtr = next; return XML_ERROR_NONE; case XML_TOK_DATA_NEWLINE: if (characterDataHandler) { XML_Char c = 0xA; characterDataHandler(handlerArg, &c, 1); } else if (defaultHandler) reportDefault(parser, enc, s, next); break; case XML_TOK_DATA_CHARS: if (characterDataHandler) { if (MUST_CONVERT(enc, s)) { for (;;) { ICHAR *dataPtr = (ICHAR *)dataBuf; XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd); *eventEndPP = next; characterDataHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf); if (s == next) break; *eventPP = s; } } else characterDataHandler(handlerArg, (XML_Char *)s, (XML_Char *)next - (XML_Char *)s); } else if (defaultHandler) reportDefault(parser, enc, s, next); break; case XML_TOK_INVALID: *eventPP = next; return XML_ERROR_INVALID_TOKEN; case XML_TOK_PARTIAL_CHAR: if (nextPtr) { *nextPtr = s; return XML_ERROR_NONE; } return XML_ERROR_PARTIAL_CHAR; case XML_TOK_PARTIAL: case XML_TOK_NONE: if (nextPtr) { *nextPtr = s; return XML_ERROR_NONE; } return XML_ERROR_UNCLOSED_CDATA_SECTION; default: abort(); } *eventPP = s = next; } /* not reached */ } #ifdef XML_DTD /* The idea here is to avoid using stack for each IGNORE section when the whole file is parsed with one call. */ static enum XML_Error ignoreSectionProcessor(XML_Parser parser, const char *start, const char *end, const char **endPtr) { enum XML_Error result = doIgnoreSection(parser, encoding, &start, end, endPtr); if (start) { processor = prologProcessor; return prologProcessor(parser, start, end, endPtr); } return result; } /* startPtr gets set to non-null is the section is closed, and to null if the section is not yet closed. */ static enum XML_Error doIgnoreSection(XML_Parser parser, const ENCODING *enc, const char **startPtr, const char *end, const char **nextPtr) { const char *next; int tok; const char *s = *startPtr; const char **eventPP; const char **eventEndPP; if (enc == encoding) { eventPP = &eventPtr; *eventPP = s; eventEndPP = &eventEndPtr; } else { eventPP = &(openInternalEntities->internalEventPtr); eventEndPP = &(openInternalEntities->internalEventEndPtr); } *eventPP = s; *startPtr = 0; tok = XmlIgnoreSectionTok(enc, s, end, &next); *eventEndPP = next; switch (tok) { case XML_TOK_IGNORE_SECT: if (defaultHandler) reportDefault(parser, enc, s, next); *startPtr = next; return XML_ERROR_NONE; case XML_TOK_INVALID: *eventPP = next; return XML_ERROR_INVALID_TOKEN; case XML_TOK_PARTIAL_CHAR: if (nextPtr) { *nextPtr = s; return XML_ERROR_NONE; } return XML_ERROR_PARTIAL_CHAR; case XML_TOK_PARTIAL: case XML_TOK_NONE: if (nextPtr) { *nextPtr = s; return XML_ERROR_NONE; } return XML_ERROR_SYNTAX; /* XML_ERROR_UNCLOSED_IGNORE_SECTION */ default: abort(); } /* not reached */ } #endif /* XML_DTD */ static enum XML_Error initializeEncoding(XML_Parser parser) { const char *s; #ifdef XML_UNICODE char encodingBuf[128]; if (!protocolEncodingName) s = 0; else { int i; for (i = 0; protocolEncodingName[i]; i++) { if (i == sizeof(encodingBuf) - 1 || (protocolEncodingName[i] & ~0x7f) != 0) { encodingBuf[0] = '\0'; break; } encodingBuf[i] = (char)protocolEncodingName[i]; } encodingBuf[i] = '\0'; s = encodingBuf; } #else s = protocolEncodingName; #endif if ((ns ? XmlInitEncodingNS : XmlInitEncoding)(&initEncoding, &encoding, s)) return XML_ERROR_NONE; return handleUnknownEncoding(parser, protocolEncodingName); } static enum XML_Error processXmlDecl(XML_Parser parser, int isGeneralTextEntity, const char *s, const char *next) { const char *encodingName = 0; const ENCODING *newEncoding = 0; const char *version; int standalone = -1; if (!(ns ? XmlParseXmlDeclNS : XmlParseXmlDecl)(isGeneralTextEntity, encoding, s, next, &eventPtr, &version, &encodingName, &newEncoding, &standalone)) return XML_ERROR_SYNTAX; if (!isGeneralTextEntity && standalone == 1) { dtd.standalone = 1; #ifdef XML_DTD if (paramEntityParsing == XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE) paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER; #endif /* XML_DTD */ } if (defaultHandler) reportDefault(parser, encoding, s, next); if (!protocolEncodingName) { if (newEncoding) { if (newEncoding->minBytesPerChar != encoding->minBytesPerChar) { eventPtr = encodingName; return XML_ERROR_INCORRECT_ENCODING; } encoding = newEncoding; } else if (encodingName) { enum XML_Error result; const XML_Char *s = poolStoreString(&tempPool, encoding, encodingName, encodingName + XmlNameLength(encoding, encodingName)); if (!s) return XML_ERROR_NO_MEMORY; result = handleUnknownEncoding(parser, s); poolDiscard(&tempPool); if (result == XML_ERROR_UNKNOWN_ENCODING) eventPtr = encodingName; return result; } } return XML_ERROR_NONE; } static enum XML_Error handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName) { if (unknownEncodingHandler) { XML_Encoding info; int i; for (i = 0; i < 256; i++) info.map[i] = -1; info.convert = 0; info.data = 0; info.release = 0; if (unknownEncodingHandler(unknownEncodingHandlerData, encodingName, &info)) { ENCODING *enc; unknownEncodingMem = malloc(XmlSizeOfUnknownEncoding()); if (!unknownEncodingMem) { if (info.release) info.release(info.data); return XML_ERROR_NO_MEMORY; } enc = (ns ? XmlInitUnknownEncodingNS : XmlInitUnknownEncoding)(unknownEncodingMem, info.map, info.convert, info.data); if (enc) { unknownEncodingData = info.data; unknownEncodingRelease = info.release; encoding = enc; return XML_ERROR_NONE; } } if (info.release) info.release(info.data); } return XML_ERROR_UNKNOWN_ENCODING; } static enum XML_Error prologInitProcessor(XML_Parser parser, const char *s, const char *end, const char **nextPtr) { enum XML_Error result = initializeEncoding(parser); if (result != XML_ERROR_NONE) return result; processor = prologProcessor; return prologProcessor(parser, s, end, nextPtr); } static enum XML_Error prologProcessor(XML_Parser parser, const char *s, const char *end, const char **nextPtr) { const char *next; int tok = XmlPrologTok(encoding, s, end, &next); return doProlog(parser, encoding, s, end, tok, next, nextPtr); } static enum XML_Error doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end, int tok, const char *next, const char **nextPtr) { #ifdef XML_DTD static const XML_Char externalSubsetName[] = { '#' , '\0' }; #endif /* XML_DTD */ const char **eventPP; const char **eventEndPP; if (enc == encoding) { eventPP = &eventPtr; eventEndPP = &eventEndPtr; } else { eventPP = &(openInternalEntities->internalEventPtr); eventEndPP = &(openInternalEntities->internalEventEndPtr); } for (;;) { int role; *eventPP = s; *eventEndPP = next; if (tok <= 0) { if (nextPtr != 0 && tok != XML_TOK_INVALID) { *nextPtr = s; return XML_ERROR_NONE; } switch (tok) { case XML_TOK_INVALID: *eventPP = next; return XML_ERROR_INVALID_TOKEN; case XML_TOK_PARTIAL: return XML_ERROR_UNCLOSED_TOKEN; case XML_TOK_PARTIAL_CHAR: return XML_ERROR_PARTIAL_CHAR; case XML_TOK_NONE: #ifdef XML_DTD if (enc != encoding) return XML_ERROR_NONE; if (parentParser) { if (XmlTokenRole(&prologState, XML_TOK_NONE, end, end, enc) == XML_ROLE_ERROR) return XML_ERROR_SYNTAX; hadExternalDoctype = 0; return XML_ERROR_NONE; } #endif /* XML_DTD */ return XML_ERROR_NO_ELEMENTS; default: tok = -tok; next = end; break; } } role = XmlTokenRole(&prologState, tok, s, next, enc); switch (role) { case XML_ROLE_XML_DECL: { enum XML_Error result = processXmlDecl(parser, 0, s, next); if (result != XML_ERROR_NONE) return result; enc = encoding; } break; case XML_ROLE_DOCTYPE_NAME: if (startDoctypeDeclHandler) { const XML_Char *name = poolStoreString(&tempPool, enc, s, next); if (!name) return XML_ERROR_NO_MEMORY; startDoctypeDeclHandler(handlerArg, name); poolClear(&tempPool); } break; #ifdef XML_DTD case XML_ROLE_TEXT_DECL: { enum XML_Error result = processXmlDecl(parser, 1, s, next); if (result != XML_ERROR_NONE) return result; enc = encoding; } break; #endif /* XML_DTD */ case XML_ROLE_DOCTYPE_PUBLIC_ID: #ifdef XML_DTD declEntity = (ENTITY *)lookup(&dtd.paramEntities, externalSubsetName, sizeof(ENTITY)); if (!declEntity) return XML_ERROR_NO_MEMORY; #endif /* XML_DTD */ /* fall through */ case XML_ROLE_ENTITY_PUBLIC_ID: if (!XmlIsPublicId(enc, s, next, eventPP)) return XML_ERROR_SYNTAX; if (declEntity) { XML_Char *tem = poolStoreString(&dtd.pool, enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar); if (!tem) return XML_ERROR_NO_MEMORY; normalizePublicId(tem); declEntity->publicId = tem; poolFinish(&dtd.pool); } break; case XML_ROLE_DOCTYPE_CLOSE: if (dtd.complete && hadExternalDoctype) { dtd.complete = 0; #ifdef XML_DTD if (paramEntityParsing && externalEntityRefHandler) { ENTITY *entity = (ENTITY *)lookup(&dtd.paramEntities, externalSubsetName, 0); if (!externalEntityRefHandler(externalEntityRefHandlerArg, 0, entity->base, entity->systemId, entity->publicId)) return XML_ERROR_EXTERNAL_ENTITY_HANDLING; } #endif /* XML_DTD */ if (!dtd.complete && !dtd.standalone && notStandaloneHandler && !notStandaloneHandler(handlerArg)) return XML_ERROR_NOT_STANDALONE; } if (endDoctypeDeclHandler) endDoctypeDeclHandler(handlerArg); break; case XML_ROLE_INSTANCE_START: processor = contentProcessor; return contentProcessor(parser, s, end, nextPtr); case XML_ROLE_ATTLIST_ELEMENT_NAME: { const XML_Char *name = poolStoreString(&dtd.pool, enc, s, next); if (!name) return XML_ERROR_NO_MEMORY; declElementType = (ELEMENT_TYPE *)lookup(&dtd.elementTypes, name, sizeof(ELEMENT_TYPE)); if (!declElementType) return XML_ERROR_NO_MEMORY; if (declElementType->name != name) poolDiscard(&dtd.pool); else { poolFinish(&dtd.pool); if (!setElementTypePrefix(parser, declElementType)) return XML_ERROR_NO_MEMORY; } break; } case XML_ROLE_ATTRIBUTE_NAME: declAttributeId = getAttributeId(parser, enc, s, next); if (!declAttributeId) return XML_ERROR_NO_MEMORY; declAttributeIsCdata = 0; declAttributeIsId = 0; break; case XML_ROLE_ATTRIBUTE_TYPE_CDATA: declAttributeIsCdata = 1; break; case XML_ROLE_ATTRIBUTE_TYPE_ID: declAttributeIsId = 1; break; case XML_ROLE_IMPLIED_ATTRIBUTE_VALUE: case XML_ROLE_REQUIRED_ATTRIBUTE_VALUE: if (dtd.complete && !defineAttribute(declElementType, declAttributeId, declAttributeIsCdata, declAttributeIsId, 0)) return XML_ERROR_NO_MEMORY; break; case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE: case XML_ROLE_FIXED_ATTRIBUTE_VALUE: { const XML_Char *attVal; enum XML_Error result = storeAttributeValue(parser, enc, declAttributeIsCdata, s + enc->minBytesPerChar, next - enc->minBytesPerChar, &dtd.pool); if (result) return result; attVal = poolStart(&dtd.pool); poolFinish(&dtd.pool); if (dtd.complete // ID attributes aren't allowed to have a default && !defineAttribute(declElementType, declAttributeId, declAttributeIsCdata, 0, attVal)) return XML_ERROR_NO_MEMORY; break; } case XML_ROLE_ENTITY_VALUE: { enum XML_Error result = storeEntityValue(parser, enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar); if (declEntity) { declEntity->textPtr = poolStart(&dtd.pool); declEntity->textLen = poolLength(&dtd.pool); poolFinish(&dtd.pool); if (internalParsedEntityDeclHandler // Check it's not a parameter entity && ((ENTITY *)lookup(&dtd.generalEntities, declEntity->name, 0) == declEntity)) { *eventEndPP = s; internalParsedEntityDeclHandler(handlerArg, declEntity->name, declEntity->textPtr, declEntity->textLen); } } else poolDiscard(&dtd.pool); if (result != XML_ERROR_NONE) return result; } break; case XML_ROLE_DOCTYPE_SYSTEM_ID: if (!dtd.standalone #ifdef XML_DTD && !paramEntityParsing #endif /* XML_DTD */ && notStandaloneHandler && !notStandaloneHandler(handlerArg)) return XML_ERROR_NOT_STANDALONE; hadExternalDoctype = 1; #ifndef XML_DTD break; #else /* XML_DTD */ if (!declEntity) { declEntity = (ENTITY *)lookup(&dtd.paramEntities, externalSubsetName, sizeof(ENTITY)); if (!declEntity) return XML_ERROR_NO_MEMORY; } /* fall through */ #endif /* XML_DTD */ case XML_ROLE_ENTITY_SYSTEM_ID: if (declEntity) { declEntity->systemId = poolStoreString(&dtd.pool, enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar); if (!declEntity->systemId) return XML_ERROR_NO_MEMORY; declEntity->base = curBase; poolFinish(&dtd.pool); } break; case XML_ROLE_ENTITY_NOTATION_NAME: if (declEntity) { declEntity->notation = poolStoreString(&dtd.pool, enc, s, next); if (!declEntity->notation) return XML_ERROR_NO_MEMORY; poolFinish(&dtd.pool); if (unparsedEntityDeclHandler) { *eventEndPP = s; unparsedEntityDeclHandler(handlerArg, declEntity->name, declEntity->base, declEntity->systemId, declEntity->publicId, declEntity->notation); } } break; case XML_ROLE_EXTERNAL_GENERAL_ENTITY_NO_NOTATION: if (declEntity && externalParsedEntityDeclHandler) { *eventEndPP = s; externalParsedEntityDeclHandler(handlerArg, declEntity->name, declEntity->base, declEntity->systemId, declEntity->publicId); } break; case XML_ROLE_GENERAL_ENTITY_NAME: { const XML_Char *name; if (XmlPredefinedEntityName(enc, s, next)) { declEntity = 0; break; } name = poolStoreString(&dtd.pool, enc, s, next); if (!name) return XML_ERROR_NO_MEMORY; if (dtd.complete) { declEntity = (ENTITY *)lookup(&dtd.generalEntities, name, sizeof(ENTITY)); if (!declEntity) return XML_ERROR_NO_MEMORY; if (declEntity->name != name) { poolDiscard(&dtd.pool); declEntity = 0; } else poolFinish(&dtd.pool); } else { poolDiscard(&dtd.pool); declEntity = 0; } } break; case XML_ROLE_PARAM_ENTITY_NAME: #ifdef XML_DTD if (dtd.complete) { const XML_Char *name = poolStoreString(&dtd.pool, enc, s, next); if (!name) return XML_ERROR_NO_MEMORY; declEntity = (ENTITY *)lookup(&dtd.paramEntities, name, sizeof(ENTITY)); if (!declEntity) return XML_ERROR_NO_MEMORY; if (declEntity->name != name) { poolDiscard(&dtd.pool); declEntity = 0; } else poolFinish(&dtd.pool); } #else /* not XML_DTD */ declEntity = 0; #endif /* not XML_DTD */ break; case XML_ROLE_NOTATION_NAME: declNotationPublicId = 0; declNotationName = 0; if (notationDeclHandler) { declNotationName = poolStoreString(&tempPool, enc, s, next); if (!declNotationName) return XML_ERROR_NO_MEMORY; poolFinish(&tempPool); } break; case XML_ROLE_NOTATION_PUBLIC_ID: if (!XmlIsPublicId(enc, s, next, eventPP)) return XML_ERROR_SYNTAX; if (declNotationName) { XML_Char *tem = poolStoreString(&tempPool, enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar); if (!tem) return XML_ERROR_NO_MEMORY; normalizePublicId(tem); declNotationPublicId = tem; poolFinish(&tempPool); } break; case XML_ROLE_NOTATION_SYSTEM_ID: if (declNotationName && notationDeclHandler) { const XML_Char *systemId = poolStoreString(&tempPool, enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar); if (!systemId) return XML_ERROR_NO_MEMORY; *eventEndPP = s; notationDeclHandler(handlerArg, declNotationName, curBase, systemId, declNotationPublicId); } poolClear(&tempPool); break; case XML_ROLE_NOTATION_NO_SYSTEM_ID: if (declNotationPublicId && notationDeclHandler) { *eventEndPP = s; notationDeclHandler(handlerArg, declNotationName, curBase, 0, declNotationPublicId); } poolClear(&tempPool); break; case XML_ROLE_ERROR: switch (tok) { case XML_TOK_PARAM_ENTITY_REF: return XML_ERROR_PARAM_ENTITY_REF; case XML_TOK_XML_DECL: return XML_ERROR_MISPLACED_XML_PI; default: return XML_ERROR_SYNTAX; } #ifdef XML_DTD case XML_ROLE_IGNORE_SECT: { enum XML_Error result; if (defaultHandler) reportDefault(parser, enc, s, next); result = doIgnoreSection(parser, enc, &next, end, nextPtr); if (!next) { processor = ignoreSectionProcessor; return result; } } break; #endif /* XML_DTD */ case XML_ROLE_GROUP_OPEN: if (prologState.level >= groupSize) { if (groupSize) groupConnector = realloc(groupConnector, groupSize *= 2); else groupConnector = malloc(groupSize = 32); if (!groupConnector) return XML_ERROR_NO_MEMORY; } groupConnector[prologState.level] = 0; break; case XML_ROLE_GROUP_SEQUENCE: if (groupConnector[prologState.level] == '|') return XML_ERROR_SYNTAX; groupConnector[prologState.level] = ','; break; case XML_ROLE_GROUP_CHOICE: if (groupConnector[prologState.level] == ',') return XML_ERROR_SYNTAX; groupConnector[prologState.level] = '|'; break; case XML_ROLE_PARAM_ENTITY_REF: #ifdef XML_DTD case XML_ROLE_INNER_PARAM_ENTITY_REF: if (paramEntityParsing && (dtd.complete || role == XML_ROLE_INNER_PARAM_ENTITY_REF)) { const XML_Char *name; ENTITY *entity; name = poolStoreString(&dtd.pool, enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar); if (!name) return XML_ERROR_NO_MEMORY; entity = (ENTITY *)lookup(&dtd.paramEntities, name, 0); poolDiscard(&dtd.pool); if (!entity) { /* FIXME what to do if !dtd.complete? */ return XML_ERROR_UNDEFINED_ENTITY; } if (entity->open) return XML_ERROR_RECURSIVE_ENTITY_REF; if (entity->textPtr) { enum XML_Error result; result = processInternalParamEntity(parser, entity); if (result != XML_ERROR_NONE) return result; break; } if (role == XML_ROLE_INNER_PARAM_ENTITY_REF) return XML_ERROR_PARAM_ENTITY_REF; if (externalEntityRefHandler) { dtd.complete = 0; entity->open = 1; if (!externalEntityRefHandler(externalEntityRefHandlerArg, 0, entity->base, entity->systemId, entity->publicId)) { entity->open = 0; return XML_ERROR_EXTERNAL_ENTITY_HANDLING; } entity->open = 0; if (dtd.complete) break; } } #endif /* XML_DTD */ if (!dtd.standalone && notStandaloneHandler && !notStandaloneHandler(handlerArg)) return XML_ERROR_NOT_STANDALONE; dtd.complete = 0; if (defaultHandler) reportDefault(parser, enc, s, next); break; case XML_ROLE_NONE: switch (tok) { case XML_TOK_PI: if (!reportProcessingInstruction(parser, enc, s, next)) return XML_ERROR_NO_MEMORY; break; case XML_TOK_COMMENT: if (!reportComment(parser, enc, s, next)) return XML_ERROR_NO_MEMORY; break; } break; } if (defaultHandler) { switch (tok) { case XML_TOK_PI: case XML_TOK_COMMENT: case XML_TOK_BOM: case XML_TOK_XML_DECL: #ifdef XML_DTD case XML_TOK_IGNORE_SECT: #endif /* XML_DTD */ case XML_TOK_PARAM_ENTITY_REF: break; default: #ifdef XML_DTD if (role != XML_ROLE_IGNORE_SECT) #endif /* XML_DTD */ reportDefault(parser, enc, s, next); } } s = next; tok = XmlPrologTok(enc, s, end, &next); } /* not reached */ } static enum XML_Error epilogProcessor(XML_Parser parser, const char *s, const char *end, const char **nextPtr) { processor = epilogProcessor; eventPtr = s; for (;;) { const char *next; int tok = XmlPrologTok(encoding, s, end, &next); eventEndPtr = next; switch (tok) { case -XML_TOK_PROLOG_S: if (defaultHandler) { eventEndPtr = end; reportDefault(parser, encoding, s, end); } /* fall through */ case XML_TOK_NONE: if (nextPtr) *nextPtr = end; return XML_ERROR_NONE; case XML_TOK_PROLOG_S: if (defaultHandler) reportDefault(parser, encoding, s, next); break; case XML_TOK_PI: if (!reportProcessingInstruction(parser, encoding, s, next)) return XML_ERROR_NO_MEMORY; break; case XML_TOK_COMMENT: if (!reportComment(parser, encoding, s, next)) return XML_ERROR_NO_MEMORY; break; case XML_TOK_INVALID: eventPtr = next; return XML_ERROR_INVALID_TOKEN; case XML_TOK_PARTIAL: if (nextPtr) { *nextPtr = s; return XML_ERROR_NONE; } return XML_ERROR_UNCLOSED_TOKEN; case XML_TOK_PARTIAL_CHAR: if (nextPtr) { *nextPtr = s; return XML_ERROR_NONE; } return XML_ERROR_PARTIAL_CHAR; default: return XML_ERROR_JUNK_AFTER_DOC_ELEMENT; } eventPtr = s = next; } } #ifdef XML_DTD static enum XML_Error processInternalParamEntity(XML_Parser parser, ENTITY *entity) { const char *s, *end, *next; int tok; enum XML_Error result; OPEN_INTERNAL_ENTITY openEntity; entity->open = 1; openEntity.next = openInternalEntities; openInternalEntities = &openEntity; openEntity.entity = entity; openEntity.internalEventPtr = 0; openEntity.internalEventEndPtr = 0; s = (char *)entity->textPtr; end = (char *)(entity->textPtr + entity->textLen); tok = XmlPrologTok(internalEncoding, s, end, &next); result = doProlog(parser, internalEncoding, s, end, tok, next, 0); entity->open = 0; openInternalEntities = openEntity.next; return result; } #endif /* XML_DTD */ static enum XML_Error errorProcessor(XML_Parser parser, const char *s, const char *end, const char **nextPtr) { return errorCode; } static enum XML_Error storeAttributeValue(XML_Parser parser, const ENCODING *enc, int isCdata, const char *ptr, const char *end, STRING_POOL *pool) { enum XML_Error result = appendAttributeValue(parser, enc, isCdata, ptr, end, pool); if (result) return result; if (!isCdata && poolLength(pool) && poolLastChar(pool) == 0x20) poolChop(pool); if (!poolAppendChar(pool, XML_T('\0'))) return XML_ERROR_NO_MEMORY; return XML_ERROR_NONE; } static enum XML_Error appendAttributeValue(XML_Parser parser, const ENCODING *enc, int isCdata, const char *ptr, const char *end, STRING_POOL *pool) { for (;;) { const char *next; int tok = XmlAttributeValueTok(enc, ptr, end, &next); switch (tok) { case XML_TOK_NONE: return XML_ERROR_NONE; case XML_TOK_INVALID: if (enc == encoding) eventPtr = next; return XML_ERROR_INVALID_TOKEN; case XML_TOK_PARTIAL: if (enc == encoding) eventPtr = ptr; return XML_ERROR_INVALID_TOKEN; case XML_TOK_CHAR_REF: { XML_Char buf[XML_ENCODE_MAX]; int i; int n = XmlCharRefNumber(enc, ptr); if (n < 0) { if (enc == encoding) eventPtr = ptr; return XML_ERROR_BAD_CHAR_REF; } if (!isCdata && n == 0x20 /* space */ && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20)) break; n = XmlEncode(n, (ICHAR *)buf); if (!n) { if (enc == encoding) eventPtr = ptr; return XML_ERROR_BAD_CHAR_REF; } for (i = 0; i < n; i++) { if (!poolAppendChar(pool, buf[i])) return XML_ERROR_NO_MEMORY; } } break; case XML_TOK_DATA_CHARS: if (!poolAppend(pool, enc, ptr, next)) return XML_ERROR_NO_MEMORY; break; break; case XML_TOK_TRAILING_CR: next = ptr + enc->minBytesPerChar; /* fall through */ case XML_TOK_ATTRIBUTE_VALUE_S: case XML_TOK_DATA_NEWLINE: if (!isCdata && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20)) break; if (!poolAppendChar(pool, 0x20)) return XML_ERROR_NO_MEMORY; break; case XML_TOK_ENTITY_REF: { const XML_Char *name; ENTITY *entity; XML_Char ch = XmlPredefinedEntityName(enc, ptr + enc->minBytesPerChar, next - enc->minBytesPerChar); if (ch) { if (!poolAppendChar(pool, ch)) return XML_ERROR_NO_MEMORY; break; } name = poolStoreString(&temp2Pool, enc, ptr + enc->minBytesPerChar, next - enc->minBytesPerChar); if (!name) return XML_ERROR_NO_MEMORY; entity = (ENTITY *)lookup(&dtd.generalEntities, name, 0); poolDiscard(&temp2Pool); if (!entity) { if (dtd.complete) { if (enc == encoding) eventPtr = ptr; return XML_ERROR_UNDEFINED_ENTITY; } } else if (entity->open) { if (enc == encoding) eventPtr = ptr; return XML_ERROR_RECURSIVE_ENTITY_REF; } else if (entity->notation) { if (enc == encoding) eventPtr = ptr; return XML_ERROR_BINARY_ENTITY_REF; } else if (!entity->textPtr) { if (enc == encoding) eventPtr = ptr; return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF; } else { enum XML_Error result; const XML_Char *textEnd = entity->textPtr + entity->textLen; entity->open = 1; result = appendAttributeValue(parser, internalEncoding, isCdata, (char *)entity->textPtr, (char *)textEnd, pool); entity->open = 0; if (result) return result; } } break; default: abort(); } ptr = next; } /* not reached */ } static enum XML_Error storeEntityValue(XML_Parser parser, const ENCODING *enc, const char *entityTextPtr, const char *entityTextEnd) { STRING_POOL *pool = &(dtd.pool); for (;;) { const char *next; int tok = XmlEntityValueTok(enc, entityTextPtr, entityTextEnd, &next); switch (tok) { case XML_TOK_PARAM_ENTITY_REF: #ifdef XML_DTD if (parentParser || enc != encoding) { enum XML_Error result; const XML_Char *name; ENTITY *entity; name = poolStoreString(&tempPool, enc, entityTextPtr + enc->minBytesPerChar, next - enc->minBytesPerChar); if (!name) return XML_ERROR_NO_MEMORY; entity = (ENTITY *)lookup(&dtd.paramEntities, name, 0); poolDiscard(&tempPool); if (!entity) { if (enc == encoding) eventPtr = entityTextPtr; return XML_ERROR_UNDEFINED_ENTITY; } if (entity->open) { if (enc == encoding) eventPtr = entityTextPtr; return XML_ERROR_RECURSIVE_ENTITY_REF; } if (entity->systemId) { if (enc == encoding) eventPtr = entityTextPtr; return XML_ERROR_PARAM_ENTITY_REF; } entity->open = 1; result = storeEntityValue(parser, internalEncoding, (char *)entity->textPtr, (char *)(entity->textPtr + entity->textLen)); entity->open = 0; if (result) return result; break; } #endif /* XML_DTD */ eventPtr = entityTextPtr; return XML_ERROR_SYNTAX; case XML_TOK_NONE: return XML_ERROR_NONE; case XML_TOK_ENTITY_REF: case XML_TOK_DATA_CHARS: if (!poolAppend(pool, enc, entityTextPtr, next)) return XML_ERROR_NO_MEMORY; break; case XML_TOK_TRAILING_CR: next = entityTextPtr + enc->minBytesPerChar; /* fall through */ case XML_TOK_DATA_NEWLINE: if (pool->end == pool->ptr && !poolGrow(pool)) return XML_ERROR_NO_MEMORY; *(pool->ptr)++ = 0xA; break; case XML_TOK_CHAR_REF: { XML_Char buf[XML_ENCODE_MAX]; int i; int n = XmlCharRefNumber(enc, entityTextPtr); if (n < 0) { if (enc == encoding) eventPtr = entityTextPtr; return XML_ERROR_BAD_CHAR_REF; } n = XmlEncode(n, (ICHAR *)buf); if (!n) { if (enc == encoding) eventPtr = entityTextPtr; return XML_ERROR_BAD_CHAR_REF; } for (i = 0; i < n; i++) { if (pool->end == pool->ptr && !poolGrow(pool)) return XML_ERROR_NO_MEMORY; *(pool->ptr)++ = buf[i]; } } break; case XML_TOK_PARTIAL: if (enc == encoding) eventPtr = entityTextPtr; return XML_ERROR_INVALID_TOKEN; case XML_TOK_INVALID: if (enc == encoding) eventPtr = next; return XML_ERROR_INVALID_TOKEN; default: abort(); } entityTextPtr = next; } /* not reached */ } static void normalizeLines(XML_Char *s) { XML_Char *p; for (;; s++) { if (*s == XML_T('\0')) return; if (*s == 0xD) break; } p = s; do { if (*s == 0xD) { *p++ = 0xA; if (*++s == 0xA) s++; } else *p++ = *s++; } while (*s); *p = XML_T('\0'); } static int reportProcessingInstruction(XML_Parser parser, const ENCODING *enc, const char *start, const char *end) { const XML_Char *target; XML_Char *data; const char *tem; if (!processingInstructionHandler) { if (defaultHandler) reportDefault(parser, enc, start, end); return 1; } start += enc->minBytesPerChar * 2; tem = start + XmlNameLength(enc, start); target = poolStoreString(&tempPool, enc, start, tem); if (!target) return 0; poolFinish(&tempPool); data = poolStoreString(&tempPool, enc, XmlSkipS(enc, tem), end - enc->minBytesPerChar*2); if (!data) return 0; normalizeLines(data); processingInstructionHandler(handlerArg, target, data); poolClear(&tempPool); return 1; } static int reportComment(XML_Parser parser, const ENCODING *enc, const char *start, const char *end) { XML_Char *data; if (!commentHandler) { if (defaultHandler) reportDefault(parser, enc, start, end); return 1; } data = poolStoreString(&tempPool, enc, start + enc->minBytesPerChar * 4, end - enc->minBytesPerChar * 3); if (!data) return 0; normalizeLines(data); commentHandler(handlerArg, data); poolClear(&tempPool); return 1; } static void reportDefault(XML_Parser parser, const ENCODING *enc, const char *s, const char *end) { if (MUST_CONVERT(enc, s)) { const char **eventPP; const char **eventEndPP; if (enc == encoding) { eventPP = &eventPtr; eventEndPP = &eventEndPtr; } else { eventPP = &(openInternalEntities->internalEventPtr); eventEndPP = &(openInternalEntities->internalEventEndPtr); } do { ICHAR *dataPtr = (ICHAR *)dataBuf; XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd); *eventEndPP = s; defaultHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf); *eventPP = s; } while (s != end); } else defaultHandler(handlerArg, (XML_Char *)s, (XML_Char *)end - (XML_Char *)s); } static int defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, int isCdata, int isId, const XML_Char *value) { DEFAULT_ATTRIBUTE *att; if (value || isId) { /* The handling of default attributes gets messed up if we have a default which duplicates a non-default. */ int i; for (i = 0; i < type->nDefaultAtts; i++) if (attId == type->defaultAtts[i].id) return 1; if (isId && !type->idAtt && !attId->xmlns) type->idAtt = attId; } if (type->nDefaultAtts == type->allocDefaultAtts) { if (type->allocDefaultAtts == 0) { type->allocDefaultAtts = 8; type->defaultAtts = malloc(type->allocDefaultAtts*sizeof(DEFAULT_ATTRIBUTE)); } else { type->allocDefaultAtts *= 2; type->defaultAtts = realloc(type->defaultAtts, type->allocDefaultAtts*sizeof(DEFAULT_ATTRIBUTE)); } if (!type->defaultAtts) return 0; } att = type->defaultAtts + type->nDefaultAtts; att->id = attId; att->value = value; att->isCdata = isCdata; if (!isCdata) attId->maybeTokenized = 1; type->nDefaultAtts += 1; return 1; } static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType) { const XML_Char *name; for (name = elementType->name; *name; name++) { if (*name == XML_T(':')) { PREFIX *prefix; const XML_Char *s; for (s = elementType->name; s != name; s++) { if (!poolAppendChar(&dtd.pool, *s)) return 0; } if (!poolAppendChar(&dtd.pool, XML_T('\0'))) return 0; prefix = (PREFIX *)lookup(&dtd.prefixes, poolStart(&dtd.pool), sizeof(PREFIX)); if (!prefix) return 0; if (prefix->name == poolStart(&dtd.pool)) poolFinish(&dtd.pool); else poolDiscard(&dtd.pool); elementType->prefix = prefix; } } return 1; } static ATTRIBUTE_ID * getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start, const char *end) { ATTRIBUTE_ID *id; const XML_Char *name; if (!poolAppendChar(&dtd.pool, XML_T('\0'))) return 0; name = poolStoreString(&dtd.pool, enc, start, end); if (!name) return 0; ++name; id = (ATTRIBUTE_ID *)lookup(&dtd.attributeIds, name, sizeof(ATTRIBUTE_ID)); if (!id) return 0; if (id->name != name) poolDiscard(&dtd.pool); else { poolFinish(&dtd.pool); if (!ns) ; else if (name[0] == 'x' && name[1] == 'm' && name[2] == 'l' && name[3] == 'n' && name[4] == 's' && (name[5] == XML_T('\0') || name[5] == XML_T(':'))) { if (name[5] == '\0') id->prefix = &dtd.defaultPrefix; else id->prefix = (PREFIX *)lookup(&dtd.prefixes, name + 6, sizeof(PREFIX)); id->xmlns = 1; } else { int i; for (i = 0; name[i]; i++) { if (name[i] == XML_T(':')) { int j; for (j = 0; j < i; j++) { if (!poolAppendChar(&dtd.pool, name[j])) return 0; } if (!poolAppendChar(&dtd.pool, XML_T('\0'))) return 0; id->prefix = (PREFIX *)lookup(&dtd.prefixes, poolStart(&dtd.pool), sizeof(PREFIX)); if (id->prefix->name == poolStart(&dtd.pool)) poolFinish(&dtd.pool); else poolDiscard(&dtd.pool); break; } } } } return id; } #define CONTEXT_SEP XML_T('\f') static const XML_Char *getContext(XML_Parser parser) { HASH_TABLE_ITER iter; int needSep = 0; if (dtd.defaultPrefix.binding) { int i; int len; if (!poolAppendChar(&tempPool, XML_T('='))) return 0; len = dtd.defaultPrefix.binding->uriLen; if (namespaceSeparator != XML_T('\0')) len--; for (i = 0; i < len; i++) if (!poolAppendChar(&tempPool, dtd.defaultPrefix.binding->uri[i])) return 0; needSep = 1; } hashTableIterInit(&iter, &(dtd.prefixes)); for (;;) { int i; int len; const XML_Char *s; PREFIX *prefix = (PREFIX *)hashTableIterNext(&iter); if (!prefix) break; if (!prefix->binding) continue; if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP)) return 0; for (s = prefix->name; *s; s++) if (!poolAppendChar(&tempPool, *s)) return 0; if (!poolAppendChar(&tempPool, XML_T('='))) return 0; len = prefix->binding->uriLen; if (namespaceSeparator != XML_T('\0')) len--; for (i = 0; i < len; i++) if (!poolAppendChar(&tempPool, prefix->binding->uri[i])) return 0; needSep = 1; } hashTableIterInit(&iter, &(dtd.generalEntities)); for (;;) { const XML_Char *s; ENTITY *e = (ENTITY *)hashTableIterNext(&iter); if (!e) break; if (!e->open) continue; if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP)) return 0; for (s = e->name; *s; s++) if (!poolAppendChar(&tempPool, *s)) return 0; needSep = 1; } if (!poolAppendChar(&tempPool, XML_T('\0'))) return 0; return tempPool.start; } static int setContext(XML_Parser parser, const XML_Char *context) { const XML_Char *s = context; while (*context != XML_T('\0')) { if (*s == CONTEXT_SEP || *s == XML_T('\0')) { ENTITY *e; if (!poolAppendChar(&tempPool, XML_T('\0'))) return 0; e = (ENTITY *)lookup(&dtd.generalEntities, poolStart(&tempPool), 0); if (e) e->open = 1; if (*s != XML_T('\0')) s++; context = s; poolDiscard(&tempPool); } else if (*s == '=') { PREFIX *prefix; if (poolLength(&tempPool) == 0) prefix = &dtd.defaultPrefix; else { if (!poolAppendChar(&tempPool, XML_T('\0'))) return 0; prefix = (PREFIX *)lookup(&dtd.prefixes, poolStart(&tempPool), sizeof(PREFIX)); if (!prefix) return 0; if (prefix->name == poolStart(&tempPool)) { prefix->name = poolCopyString(&dtd.pool, prefix->name); if (!prefix->name) return 0; } poolDiscard(&tempPool); } for (context = s + 1; *context != CONTEXT_SEP && *context != XML_T('\0'); context++) if (!poolAppendChar(&tempPool, *context)) return 0; if (!poolAppendChar(&tempPool, XML_T('\0'))) return 0; if (!addBinding(parser, prefix, 0, poolStart(&tempPool), &inheritedBindings)) return 0; poolDiscard(&tempPool); if (*context != XML_T('\0')) ++context; s = context; } else { if (!poolAppendChar(&tempPool, *s)) return 0; s++; } } return 1; } static void normalizePublicId(XML_Char *publicId) { XML_Char *p = publicId; XML_Char *s; for (s = publicId; *s; s++) { switch (*s) { case 0x20: case 0xD: case 0xA: if (p != publicId && p[-1] != 0x20) *p++ = 0x20; break; default: *p++ = *s; } } if (p != publicId && p[-1] == 0x20) --p; *p = XML_T('\0'); } static int dtdInit(DTD *p) { poolInit(&(p->pool)); hashTableInit(&(p->generalEntities)); hashTableInit(&(p->elementTypes)); hashTableInit(&(p->attributeIds)); hashTableInit(&(p->prefixes)); p->complete = 1; p->standalone = 0; #ifdef XML_DTD hashTableInit(&(p->paramEntities)); #endif /* XML_DTD */ p->defaultPrefix.name = 0; p->defaultPrefix.binding = 0; return 1; } #ifdef XML_DTD static void dtdSwap(DTD *p1, DTD *p2) { DTD tem; memcpy(&tem, p1, sizeof(DTD)); memcpy(p1, p2, sizeof(DTD)); memcpy(p2, &tem, sizeof(DTD)); } #endif /* XML_DTD */ static void dtdDestroy(DTD *p) { HASH_TABLE_ITER iter; hashTableIterInit(&iter, &(p->elementTypes)); for (;;) { ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter); if (!e) break; if (e->allocDefaultAtts != 0) free(e->defaultAtts); } hashTableDestroy(&(p->generalEntities)); #ifdef XML_DTD hashTableDestroy(&(p->paramEntities)); #endif /* XML_DTD */ hashTableDestroy(&(p->elementTypes)); hashTableDestroy(&(p->attributeIds)); hashTableDestroy(&(p->prefixes)); poolDestroy(&(p->pool)); } /* Do a deep copy of the DTD. Return 0 for out of memory; non-zero otherwise. The new DTD has already been initialized. */ static int dtdCopy(DTD *newDtd, const DTD *oldDtd) { HASH_TABLE_ITER iter; /* Copy the prefix table. */ hashTableIterInit(&iter, &(oldDtd->prefixes)); for (;;) { const XML_Char *name; const PREFIX *oldP = (PREFIX *)hashTableIterNext(&iter); if (!oldP) break; name = poolCopyString(&(newDtd->pool), oldP->name); if (!name) return 0; if (!lookup(&(newDtd->prefixes), name, sizeof(PREFIX))) return 0; } hashTableIterInit(&iter, &(oldDtd->attributeIds)); /* Copy the attribute id table. */ for (;;) { ATTRIBUTE_ID *newA; const XML_Char *name; const ATTRIBUTE_ID *oldA = (ATTRIBUTE_ID *)hashTableIterNext(&iter); if (!oldA) break; /* Remember to allocate the scratch byte before the name. */ if (!poolAppendChar(&(newDtd->pool), XML_T('\0'))) return 0; name = poolCopyString(&(newDtd->pool), oldA->name); if (!name) return 0; ++name; newA = (ATTRIBUTE_ID *)lookup(&(newDtd->attributeIds), name, sizeof(ATTRIBUTE_ID)); if (!newA) return 0; newA->maybeTokenized = oldA->maybeTokenized; if (oldA->prefix) { newA->xmlns = oldA->xmlns; if (oldA->prefix == &oldDtd->defaultPrefix) newA->prefix = &newDtd->defaultPrefix; else newA->prefix = (PREFIX *)lookup(&(newDtd->prefixes), oldA->prefix->name, 0); } } /* Copy the element type table. */ hashTableIterInit(&iter, &(oldDtd->elementTypes)); for (;;) { int i; ELEMENT_TYPE *newE; const XML_Char *name; const ELEMENT_TYPE *oldE = (ELEMENT_TYPE *)hashTableIterNext(&iter); if (!oldE) break; name = poolCopyString(&(newDtd->pool), oldE->name); if (!name) return 0; newE = (ELEMENT_TYPE *)lookup(&(newDtd->elementTypes), name, sizeof(ELEMENT_TYPE)); if (!newE) return 0; if (oldE->nDefaultAtts) { newE->defaultAtts = (DEFAULT_ATTRIBUTE *)malloc(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE)); if (!newE->defaultAtts) return 0; } if (oldE->idAtt) newE->idAtt = (ATTRIBUTE_ID *)lookup(&(newDtd->attributeIds), oldE->idAtt->name, 0); newE->allocDefaultAtts = newE->nDefaultAtts = oldE->nDefaultAtts; if (oldE->prefix) newE->prefix = (PREFIX *)lookup(&(newDtd->prefixes), oldE->prefix->name, 0); for (i = 0; i < newE->nDefaultAtts; i++) { newE->defaultAtts[i].id = (ATTRIBUTE_ID *)lookup(&(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0); newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata; if (oldE->defaultAtts[i].value) { newE->defaultAtts[i].value = poolCopyString(&(newDtd->pool), oldE->defaultAtts[i].value); if (!newE->defaultAtts[i].value) return 0; } else newE->defaultAtts[i].value = 0; } } /* Copy the entity tables. */ if (!copyEntityTable(&(newDtd->generalEntities), &(newDtd->pool), &(oldDtd->generalEntities))) return 0; #ifdef XML_DTD if (!copyEntityTable(&(newDtd->paramEntities), &(newDtd->pool), &(oldDtd->paramEntities))) return 0; #endif /* XML_DTD */ newDtd->complete = oldDtd->complete; newDtd->standalone = oldDtd->standalone; return 1; } static int copyEntityTable(HASH_TABLE *newTable, STRING_POOL *newPool, const HASH_TABLE *oldTable) { HASH_TABLE_ITER iter; const XML_Char *cachedOldBase = 0; const XML_Char *cachedNewBase = 0; hashTableIterInit(&iter, oldTable); for (;;) { ENTITY *newE; const XML_Char *name; const ENTITY *oldE = (ENTITY *)hashTableIterNext(&iter); if (!oldE) break; name = poolCopyString(newPool, oldE->name); if (!name) return 0; newE = (ENTITY *)lookup(newTable, name, sizeof(ENTITY)); if (!newE) return 0; if (oldE->systemId) { const XML_Char *tem = poolCopyString(newPool, oldE->systemId); if (!tem) return 0; newE->systemId = tem; if (oldE->base) { if (oldE->base == cachedOldBase) newE->base = cachedNewBase; else { cachedOldBase = oldE->base; tem = poolCopyString(newPool, cachedOldBase); if (!tem) return 0; cachedNewBase = newE->base = tem; } } } else { const XML_Char *tem = poolCopyStringN(newPool, oldE->textPtr, oldE->textLen); if (!tem) return 0; newE->textPtr = tem; newE->textLen = oldE->textLen; } if (oldE->notation) { const XML_Char *tem = poolCopyString(newPool, oldE->notation); if (!tem) return 0; newE->notation = tem; } } return 1; } #define INIT_SIZE 64 static int keyeq(KEY s1, KEY s2) { for (; *s1 == *s2; s1++, s2++) if (*s1 == 0) return 1; return 0; } static unsigned long hash(KEY s) { unsigned long h = 0; while (*s) h = (h << 5) + h + (unsigned char)*s++; return h; } static NAMED *lookup(HASH_TABLE *table, KEY name, size_t createSize) { size_t i; if (table->size == 0) { if (!createSize) return 0; table->v = calloc(INIT_SIZE, sizeof(NAMED *)); if (!table->v) return 0; table->size = INIT_SIZE; table->usedLim = INIT_SIZE / 2; i = hash(name) & (table->size - 1); } else { unsigned long h = hash(name); for (i = h & (table->size - 1); table->v[i]; i == 0 ? i = table->size - 1 : --i) { if (keyeq(name, table->v[i]->name)) return table->v[i]; } if (!createSize) return 0; if (table->used == table->usedLim) { /* check for overflow */ size_t newSize = table->size * 2; NAMED **newV = calloc(newSize, sizeof(NAMED *)); if (!newV) return 0; for (i = 0; i < table->size; i++) if (table->v[i]) { size_t j; for (j = hash(table->v[i]->name) & (newSize - 1); newV[j]; j == 0 ? j = newSize - 1 : --j) ; newV[j] = table->v[i]; } free(table->v); table->v = newV; table->size = newSize; table->usedLim = newSize/2; for (i = h & (table->size - 1); table->v[i]; i == 0 ? i = table->size - 1 : --i) ; } } table->v[i] = calloc(1, createSize); if (!table->v[i]) return 0; table->v[i]->name = name; (table->used)++; return table->v[i]; } static void hashTableDestroy(HASH_TABLE *table) { size_t i; for (i = 0; i < table->size; i++) { NAMED *p = table->v[i]; if (p) free(p); } if (table->v) free(table->v); } static void hashTableInit(HASH_TABLE *p) { p->size = 0; p->usedLim = 0; p->used = 0; p->v = 0; } static void hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table) { iter->p = table->v; iter->end = iter->p + table->size; } static NAMED *hashTableIterNext(HASH_TABLE_ITER *iter) { while (iter->p != iter->end) { NAMED *tem = *(iter->p)++; if (tem) return tem; } return 0; } static void poolInit(STRING_POOL *pool) { pool->blocks = 0; pool->freeBlocks = 0; pool->start = 0; pool->ptr = 0; pool->end = 0; } static void poolClear(STRING_POOL *pool) { if (!pool->freeBlocks) pool->freeBlocks = pool->blocks; else { BLOCK *p = pool->blocks; while (p) { BLOCK *tem = p->next; p->next = pool->freeBlocks; pool->freeBlocks = p; p = tem; } } pool->blocks = 0; pool->start = 0; pool->ptr = 0; pool->end = 0; } static void poolDestroy(STRING_POOL *pool) { BLOCK *p = pool->blocks; while (p) { BLOCK *tem = p->next; free(p); p = tem; } pool->blocks = 0; p = pool->freeBlocks; while (p) { BLOCK *tem = p->next; free(p); p = tem; } pool->freeBlocks = 0; pool->ptr = 0; pool->start = 0; pool->end = 0; } static XML_Char *poolAppend(STRING_POOL *pool, const ENCODING *enc, const char *ptr, const char *end) { if (!pool->ptr && !poolGrow(pool)) return 0; for (;;) { XmlConvert(enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end); if (ptr == end) break; if (!poolGrow(pool)) return 0; } return pool->start; } static const XML_Char *poolCopyString(STRING_POOL *pool, const XML_Char *s) { do { if (!poolAppendChar(pool, *s)) return 0; } while (*s++); s = pool->start; poolFinish(pool); return s; } static const XML_Char *poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n) { if (!pool->ptr && !poolGrow(pool)) return 0; for (; n > 0; --n, s++) { if (!poolAppendChar(pool, *s)) return 0; } s = pool->start; poolFinish(pool); return s; } static XML_Char *poolStoreString(STRING_POOL *pool, const ENCODING *enc, const char *ptr, const char *end) { if (!poolAppend(pool, enc, ptr, end)) return 0; if (pool->ptr == pool->end && !poolGrow(pool)) return 0; *(pool->ptr)++ = 0; return pool->start; } static int poolGrow(STRING_POOL *pool) { if (pool->freeBlocks) { if (pool->start == 0) { pool->blocks = pool->freeBlocks; pool->freeBlocks = pool->freeBlocks->next; pool->blocks->next = 0; pool->start = pool->blocks->s; pool->end = pool->start + pool->blocks->size; pool->ptr = pool->start; return 1; } if (pool->end - pool->start < pool->freeBlocks->size) { BLOCK *tem = pool->freeBlocks->next; pool->freeBlocks->next = pool->blocks; pool->blocks = pool->freeBlocks; pool->freeBlocks = tem; memcpy(pool->blocks->s, pool->start, (pool->end - pool->start) * sizeof(XML_Char)); pool->ptr = pool->blocks->s + (pool->ptr - pool->start); pool->start = pool->blocks->s; pool->end = pool->start + pool->blocks->size; return 1; } } if (pool->blocks && pool->start == pool->blocks->s) { int blockSize = (pool->end - pool->start)*2; pool->blocks = realloc(pool->blocks, offsetof(BLOCK, s) + blockSize * sizeof(XML_Char)); if (!pool->blocks) return 0; pool->blocks->size = blockSize; pool->ptr = pool->blocks->s + (pool->ptr - pool->start); pool->start = pool->blocks->s; pool->end = pool->start + blockSize; } else { BLOCK *tem; int blockSize = pool->end - pool->start; if (blockSize < INIT_BLOCK_SIZE) blockSize = INIT_BLOCK_SIZE; else blockSize *= 2; tem = malloc(offsetof(BLOCK, s) + blockSize * sizeof(XML_Char)); if (!tem) return 0; tem->size = blockSize; tem->next = pool->blocks; pool->blocks = tem; if (pool->ptr != pool->start) memcpy(tem->s, pool->start, (pool->ptr - pool->start) * sizeof(XML_Char)); pool->ptr = tem->s + (pool->ptr - pool->start); pool->start = tem->s; pool->end = tem->s + blockSize; } return 1; } matanza-0.13/ChangeLog0000644000175000017500000004364107222162472015026 0ustar boradminboradminTue Dec 26 13:36:27 COT 2000 Alejandro Forero Cuervo * Wed Sep 27 11:41:26 COT 2000 Alejandro Forero Cuervo * Version 0.9 is released. * matanza.w (@, PLAYER_INSIDE): The macro PLAYER_INSIDE was added. Code was changed to use the new macro. * matanza.w (@): Now we check the value of arg_limits when moving the ship. (@): We now accept parameter `--limits'. * matanza.w (@): We now accept parameter `--no-radar'. If given, we set arg_radar to 0. (@): Added variable arg_radar, defaulting to 1; (draw_world): If arg_radar evaluates to false, we don't draw the directions to reach players. * matanza.w (draw_world): Now before drawing ships, we consider the value of their visible attribute. (player_input): Command `i' toggles the value of the visible attribute of a ship unless it can't be invisible anymore. This is done in macro @. (@): If player is invisible, invisible_exp is decreased. When it gets to 0, the player becomes visible. (start_game): We set the visible and visible_exp fields of the player to 1 and arg_visible_initial respectively. (@): We accept argument --invisibility and store the required_argument in arg_visible_init. (@): Added argument arg_visible_init. Tue Sep 19 22:33:12 COT 2000 Alejandro Forero Cuervo * matanza.w (@): Empty macro removed. * matanza.w (@): Increased the default values for arg_speed_max and arg_ang_speed_max. * matanza.w (mat_bullet_new): When the player runs out of bullets of a given type, we show him a message. (@): Added variables mat_bullets_name and mat_bullets_hit. (@): Macro added, with code previously in @. Now, however, when a player hits another one, we print a message depending on the type of the bullet. * matanza.w (mat_image_draw): Fixed assert (matanza.w:3501). Hopefully. * shipreal.c (mat_graph_astbig): Variable added. matanza.w (@): Now we calculate the rotations for the asteroids and flood the world with an initial ammount of them. (@): Macro added. (@): Added variables mat_ast_head and mat_ast_cur. (@): Added definition MatAst. (@, @): Macros added. (@): We now do @. (@): Added variable arg_ast_num. (@): Added command line argument `--asteroids'. * matanza.w (@): Removed argument --space and added argument --air. (@): arg_space now defalts to true. Mon Sep 18 19:20:55 COT 2000 Alejandro Forero Cuervo : * matanza.w (SPEED_MAX, @): Variable arg_speed_max was added to replace SPEED_MAX. (@): We receive argument `--speed-max' and set arg_speed_max. The help information was updated. * matanza.w (@, ANGLE_SPEED_MAX): Variable arg_ang_speed_max was added to replace ANGLE_SPEED_MAX. (@): We receive argument `--ang-speed-max' and set arg_ang_speed_max. The help information was updated. (player_input): When we receive 'h' and 'l', if arg_ang_speed_max is 0, we leave ship_angle_speed unmodified and rotate the ship. * matanza.w (@): Now we accept parameters `--fly-back', `--brake' and `--space' and set variables arg_fly_back, arg_brake and arg_space to 1, 1 and 1 when we receive them. The help information (for `--help') was updated as well. (@): Variables arg_fly_back, arg_brake and arg_space added. (player_input): When the player enters 'h' or 'l', if arg_space evaluates to false, we recalculate ship_speed_x and ship_speed_y. When the player enters 'j', if brake evaluats to false we do nothing. Also when the player enters 'j', if arg_fly_back and arg_space evaluate to false, we never let the ship fly backwards. When the player enters 'j' or 'k' and arg_space evaluates to true, rather than just increase ship_speed and recalculate ship_speed_x and ship_speed_y, we modify ship_speed_x and ship_speed_y depending on the player's angle and recalculate ship_speed. (@): If arg_space evaluates to true, we don't recalculate ship_speed_x nor ship_speed_y. * matanza.w (@, MatPlayer): Fields ship_pos_x and ship_pos_y were changed to type double. * matanza.w (@, cos_ang, sin_ang): Added functions cos_ang and sin_ang. All the time we are calculating the sin/cos of one angle from a set of arg_ang predefined angles so now we keep a cache of these values. Calls to sin/cos in many places where replaced by calls to these functions. * matanza.w (@, MatPlayer): Fields ship_speed_x and ship_speed_y were added. (@): Variable arg_space was added. (player_input): When we get 'j' or 'k', we also set ship_speed_x and ship_speed_y. (@): We now use ship_speed_x and ship_speed_y. (mat_bullet_new): We now use ship_speed_x and ship_speed_y rather than ship_speed. (@): Now we set ship_speed_x and ship_speed_y to 0. (@): We recalculate ship_speed_x and ship_speed_y whenever the ship rotates. Sun Sep 17 10:30:22 COT 2000 Alejandro Forero Cuervo * matanza.w (@): Rewrite. * matanza.w (@): Added field team_next. * matanza.w (@): Now rather than bitch and refuse to run, this macro bitches and fixes things. * shipreal.c (mat_graph_missile): Increased size of missiles 2 and 3. * matanza.w (@): We no longer call key_handler if the character is 0. * matanza.w (mat_mainmenu_anim): Fixed cosmetic bug. * matanza.w (MAXNAMELEN): Macro renamed to MAT_USER_MAX for consistency. Default value is now 8. (MAT_PASSWORD_MAX): Macro introduced. Default value is 8. (@
): Now we consider the values in MAT_USER_MAX and MAT_PASSWORD_MAX to draw the widgets. (mat_mainmenu_key): Now we consider the values in MAT_USER_MAX and MAT_PASSWORD_MAX when accepting input. * matanza.w (@): Added more names. * matanza.w (@): Removed mat_defparams. (MatPlayer): Removed field driverparams. * matanza.w (start_game, mat_mainmenu_key): Now we print the initial messages (calling @) in mat_mainmenu_key rather than start_game. The same goes for setting p->graph_randomval and p->times_dead to 0. * matanza.w (start_game): We no longer increase players_real nor set the players state. * matanza.w (@
): Added field texterr. (mat_mainmenu_key): If an error takes place (eg. the player enters an invalid password) we set texterr to a description. Whenever we receive a character, we set it back to 0. (@
): If texterr is set, we show it. * matanza.w (@
): If arg_password is NULL, we no longer show the widget for entering the password. * matanza.w (@): Added variables mat_bullets_damage mat_bullets_speed, mat_bullets_back, mat_bullets_bexp and mat_bullets_pexp. * matanza.w (mat_ship, mat_missile): Now we allocate space for these variables dynamically. * (player_input): Now we understand command `n'! * matanza.w (@): If parameter `--no-chat' is used, we set arg_chat to 0. (player_input): If arg_chat evaluates to false, we don't let the player go into KEY_STATE_BUFFER. * matanza.w (@): Macro added. (@): Type added. (@, arg_teams): Variable added to hold the head of the list of teams. (@): We now recognize argument `--team'. (@
): Added filed team. (@
): If the game is in teams mode, we display the currently selected team. (@, arg_teams_safe): Variable added, defaults to 0. (@): Bullets don't hit players of the same team as the one who shot them if arg_teams_safe evaluates to true. (@): If we receive parameter `--team-safe', we set arg_teams_safe to 1. * matanza.w (@
): Size for the password was increased. If no password was specified using the command line arguments, we don't prompt for it. (@, arg_password): Variable added. (@): We now look for option `--password' and, if specified, set arg_password. * matanza.w (@
): Small optimization. No need to call mat_graph_render and mat_graph_flush here. * matanza.w (mat_bullet_new, player_input): The prototype of mat_bullet_new has changed. Adjustments made on player_input. The return value of mat_bullet_new was fixed. * matanza.w (@): Added field angle to MatBullet. * matanza.w (@): Fixed sprintf with invalid conversion type. * matanza.w (mat_image_draw): Added a cast. * matanza.w (@, @, ANG): Added command line argument arg_ang. * shipreal.c (mat_missile): Added images for two more kinds of missiles. * matanza.w (@): Macro added to check for the values from the command line arguments and report errors. * matanza.w (ship_bullets, ship_missiles): We removed field ship_missiles from the MatPlayer struct and now we use an array ship_bullets for the different kinds of bullets. * matanza.w (mat_image_draw): Fixed asserts. * matanza.w (@, arg_lives): Now we accept parameter `--lives'. * matanza.w (@): If a player runs out of lives, he is sent to the main menu. * matanza.w (player_input): Fixed a bug: When a player hit `p', his ship would start to rotate to the right. Thu Sep 14 21:12:47 COT 2000 Alejandro Forero Cuervo * Version 0.6 is released. * matanza.w (@, mat_image_draw): Fixed asserts. Tue Sep 12 19:56:06 COT 2000 Alejandro Forero Cuervo * Version 0.5 is released. * matanza.w (mat_player_free): Now we show the right version number. * matanza.w (draw_world): The background is now drawn before everything else. * matanza.w (@): We now give the player a default initial name, randomly chosen from a list. * matanza.w (@): When a player dies, we don't send it to the main menu but have him reappear. Also, we increase her variable times_dead. * matanza.w (@): Added field times_dead to hold a count of the number of times the player has died. * matanza.w (@): Changed some code I could no longer understand (in one assert; probably harmless). * matanza.w (start_game, @): Now we initialize the structs for the messages in @. * matanza.w (@): Now we show the number of times the player has died. * matanza.w (@): We initialize the rand() seed depending on the time. * matanza.w (mat_image_draw): Added a lot of casts to pos_x and pos_y and fixed an assert that had an `or' instead of an `and'. * matanza.w (@): Bug fix. * matanza.w (@, mat_flush): Bug fix related to white backgrounds. Sat Sep 9 04:40:50 COT 2000 Alejandro Forero Cuervo * Version 0.4 released. * matanza.w (@): Adjustments made to keep things working when the player specifies different map sizes. * matanza.w (@): Bug fix. * matanza.w (mat_image_draw): Bug fix. * matanza.w (@, arg_health, arg_mapsize_x, arg_mapsize_y, INITIAL_HEALTH, MAPSIZEX, MAPSIZEY): Now we use command line options `--health', `--mapsize-x' and `--mapsize-y', storing their arguments * matanza.w (@): Bug fix. Fri Sep 8 12:51:34 COT 2000 Alejandro Forero Cuervo * matanza.w (mat_ship): Variable is now of type MatImage. Many adjustments made on code that referenced it. * matanza.w (@, mat_ship_palettes): Added code to use different palettes when drawing images. * matanza.w (MAT_GRAPH_IMGWIDTH, MAT_GRAPH_IMGHEIGHT, arg_imgwidth, arg_imgheight): Now we use arg_imgwidth and arg_imgheight instead of the hard-coded definitions before. * matanza.w (@): If we get --imgwidth or --imgheight, we store the arguments in arg_imgwidth and arg_imgheight respectively. * matanza.w (@): Now we understand parameter --version. * matanza.w (@): Now we simply call mat_image_draw. Thu Sep 7 10:12:55 COT 2000 Alejandro Forero Cuervo * matanza.w (mat_animation_cancel, mat_mainmenu_key): We now ignore '\r'. This was a bug because some clients sent '\r\n' when RET was pressed so the server considered it two RETs. * matanza.w (@, @): Variable supported was removed; now we use MAT_GRAPH_SUPPORTED everywhere. * matanza.w (@): Variable arg_bold added. It defaults to false. * matanza.w (@): If the user specifies `--bold', set arg_bold to true. It will be false otherwise. * matanza.w (MAT_GRAPH_SUPPORTED): If arg_bold evaluates to true, use bold characters. * matanza.w (player_input): Bug fix in the code for launching missiles. * matanza.w (player_input): Fixed invocations of mat_bullet_new. * matanza.w (mat_bullet_new): Now we accept a new parameter, img, to set the image used for the bullet. * matanza.w: @ was renamed to @. The invocation at @ was fixed. * matanza.w (@): The macro was added. It is called from @. * matanza.w (@): Struct added. * shipreal.c (mat_graph_missile): Variable added. Tue Sep 5 20:25:39 COT 2000 Alejandro Forero Cuervo * matanza.w (mat_flush): Bug fix, the cursor was moved to the wrong position sometimes. * matanza.w (player_input): Made it possible to shot bullets backwards. * matanza.w (mat_bullet_new): Function added to reuse code to create bullets. * matanza.w (mat_player_free): Now we decrease players_real here. * matanza.w (mat_graph_resize): The line at the bottom is now used. Mon Sep 4 19:55:06 COT 2000 Alejandro Forero Cuervo * First release. matanza-0.13/iasciitab.h0000644000175000017500000000344707254453527015366 0ustar boradminboradmin/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd See the file copying.txt for copying permission. */ /* Like asciitab.h, except that 0xD has code BT_S rather than BT_CR */ /* 0x00 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, /* 0x04 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, /* 0x08 */ BT_NONXML, BT_S, BT_LF, BT_NONXML, /* 0x0C */ BT_NONXML, BT_S, BT_NONXML, BT_NONXML, /* 0x10 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, /* 0x14 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, /* 0x18 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, /* 0x1C */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, /* 0x20 */ BT_S, BT_EXCL, BT_QUOT, BT_NUM, /* 0x24 */ BT_OTHER, BT_PERCNT, BT_AMP, BT_APOS, /* 0x28 */ BT_LPAR, BT_RPAR, BT_AST, BT_PLUS, /* 0x2C */ BT_COMMA, BT_MINUS, BT_NAME, BT_SOL, /* 0x30 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT, /* 0x34 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT, /* 0x38 */ BT_DIGIT, BT_DIGIT, BT_COLON, BT_SEMI, /* 0x3C */ BT_LT, BT_EQUALS, BT_GT, BT_QUEST, /* 0x40 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX, /* 0x44 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT, /* 0x48 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0x4C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0x50 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0x54 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0x58 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_LSQB, /* 0x5C */ BT_OTHER, BT_RSQB, BT_OTHER, BT_NMSTRT, /* 0x60 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX, /* 0x64 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT, /* 0x68 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0x6C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0x70 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0x74 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0x78 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER, /* 0x7C */ BT_VERBAR, BT_OTHER, BT_OTHER, BT_OTHER, matanza-0.13/xmltok.c0000644000175000017500000011162007254522236014732 0ustar boradminboradmin/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd See the file copying.txt for copying permission. */ #include "xmldef.h" #include "xmltok.h" #include "nametab.h" #ifdef XML_DTD #define IGNORE_SECTION_TOK_VTABLE , PREFIX(ignoreSectionTok) #else #define IGNORE_SECTION_TOK_VTABLE /* as nothing */ #endif #define VTABLE1 \ { PREFIX(prologTok), PREFIX(contentTok), \ PREFIX(cdataSectionTok) IGNORE_SECTION_TOK_VTABLE }, \ { PREFIX(attributeValueTok), PREFIX(entityValueTok) }, \ PREFIX(sameName), \ PREFIX(nameMatchesAscii), \ PREFIX(nameLength), \ PREFIX(skipS), \ PREFIX(getAtts), \ PREFIX(charRefNumber), \ PREFIX(predefinedEntityName), \ PREFIX(updatePosition), \ PREFIX(isPublicId) #define VTABLE VTABLE1, PREFIX(toUtf8), PREFIX(toUtf16) #define UCS2_GET_NAMING(pages, hi, lo) \ (namingBitmap[(pages[hi] << 3) + ((lo) >> 5)] & (1 << ((lo) & 0x1F))) /* A 2 byte UTF-8 representation splits the characters 11 bits between the bottom 5 and 6 bits of the bytes. We need 8 bits to index into pages, 3 bits to add to that index and 5 bits to generate the mask. */ #define UTF8_GET_NAMING2(pages, byte) \ (namingBitmap[((pages)[(((byte)[0]) >> 2) & 7] << 3) \ + ((((byte)[0]) & 3) << 1) \ + ((((byte)[1]) >> 5) & 1)] \ & (1 << (((byte)[1]) & 0x1F))) /* A 3 byte UTF-8 representation splits the characters 16 bits between the bottom 4, 6 and 6 bits of the bytes. We need 8 bits to index into pages, 3 bits to add to that index and 5 bits to generate the mask. */ #define UTF8_GET_NAMING3(pages, byte) \ (namingBitmap[((pages)[((((byte)[0]) & 0xF) << 4) \ + ((((byte)[1]) >> 2) & 0xF)] \ << 3) \ + ((((byte)[1]) & 3) << 1) \ + ((((byte)[2]) >> 5) & 1)] \ & (1 << (((byte)[2]) & 0x1F))) #define UTF8_GET_NAMING(pages, p, n) \ ((n) == 2 \ ? UTF8_GET_NAMING2(pages, (const unsigned char *)(p)) \ : ((n) == 3 \ ? UTF8_GET_NAMING3(pages, (const unsigned char *)(p)) \ : 0)) #define UTF8_INVALID3(p) \ ((*p) == 0xED \ ? (((p)[1] & 0x20) != 0) \ : ((*p) == 0xEF \ ? ((p)[1] == 0xBF && ((p)[2] == 0xBF || (p)[2] == 0xBE)) \ : 0)) #define UTF8_INVALID4(p) ((*p) == 0xF4 && ((p)[1] & 0x30) != 0) static int isNever(const ENCODING *enc, const char *p) { return 0; } static int utf8_isName2(const ENCODING *enc, const char *p) { return UTF8_GET_NAMING2(namePages, (const unsigned char *)p); } static int utf8_isName3(const ENCODING *enc, const char *p) { return UTF8_GET_NAMING3(namePages, (const unsigned char *)p); } #define utf8_isName4 isNever static int utf8_isNmstrt2(const ENCODING *enc, const char *p) { return UTF8_GET_NAMING2(nmstrtPages, (const unsigned char *)p); } static int utf8_isNmstrt3(const ENCODING *enc, const char *p) { return UTF8_GET_NAMING3(nmstrtPages, (const unsigned char *)p); } #define utf8_isNmstrt4 isNever #define utf8_isInvalid2 isNever static int utf8_isInvalid3(const ENCODING *enc, const char *p) { return UTF8_INVALID3((const unsigned char *)p); } static int utf8_isInvalid4(const ENCODING *enc, const char *p) { return UTF8_INVALID4((const unsigned char *)p); } struct normal_encoding { ENCODING enc; unsigned char type[256]; #ifdef XML_MIN_SIZE int (*byteType)(const ENCODING *, const char *); int (*isNameMin)(const ENCODING *, const char *); int (*isNmstrtMin)(const ENCODING *, const char *); int (*byteToAscii)(const ENCODING *, const char *); int (*charMatches)(const ENCODING *, const char *, int); #endif /* XML_MIN_SIZE */ int (*isName2)(const ENCODING *, const char *); int (*isName3)(const ENCODING *, const char *); int (*isName4)(const ENCODING *, const char *); int (*isNmstrt2)(const ENCODING *, const char *); int (*isNmstrt3)(const ENCODING *, const char *); int (*isNmstrt4)(const ENCODING *, const char *); int (*isInvalid2)(const ENCODING *, const char *); int (*isInvalid3)(const ENCODING *, const char *); int (*isInvalid4)(const ENCODING *, const char *); }; #ifdef XML_MIN_SIZE #define STANDARD_VTABLE(E) \ E ## byteType, \ E ## isNameMin, \ E ## isNmstrtMin, \ E ## byteToAscii, \ E ## charMatches, #else #define STANDARD_VTABLE(E) /* as nothing */ #endif #define NORMAL_VTABLE(E) \ E ## isName2, \ E ## isName3, \ E ## isName4, \ E ## isNmstrt2, \ E ## isNmstrt3, \ E ## isNmstrt4, \ E ## isInvalid2, \ E ## isInvalid3, \ E ## isInvalid4 static int checkCharRefNumber(int); #include "xmltok_impl.h" #include "ascii.h" #ifdef XML_MIN_SIZE #define sb_isNameMin isNever #define sb_isNmstrtMin isNever #endif #ifdef XML_MIN_SIZE #define MINBPC(enc) ((enc)->minBytesPerChar) #else /* minimum bytes per character */ #define MINBPC(enc) 1 #endif #define SB_BYTE_TYPE(enc, p) \ (((struct normal_encoding *)(enc))->type[(unsigned char)*(p)]) #ifdef XML_MIN_SIZE static int sb_byteType(const ENCODING *enc, const char *p) { return SB_BYTE_TYPE(enc, p); } #define BYTE_TYPE(enc, p) \ (((const struct normal_encoding *)(enc))->byteType(enc, p)) #else #define BYTE_TYPE(enc, p) SB_BYTE_TYPE(enc, p) #endif #ifdef XML_MIN_SIZE #define BYTE_TO_ASCII(enc, p) \ (((const struct normal_encoding *)(enc))->byteToAscii(enc, p)) static int sb_byteToAscii(const ENCODING *enc, const char *p) { return *p; } #else #define BYTE_TO_ASCII(enc, p) (*(p)) #endif #define IS_NAME_CHAR(enc, p, n) \ (((const struct normal_encoding *)(enc))->isName ## n(enc, p)) #define IS_NMSTRT_CHAR(enc, p, n) \ (((const struct normal_encoding *)(enc))->isNmstrt ## n(enc, p)) #define IS_INVALID_CHAR(enc, p, n) \ (((const struct normal_encoding *)(enc))->isInvalid ## n(enc, p)) #ifdef XML_MIN_SIZE #define IS_NAME_CHAR_MINBPC(enc, p) \ (((const struct normal_encoding *)(enc))->isNameMin(enc, p)) #define IS_NMSTRT_CHAR_MINBPC(enc, p) \ (((const struct normal_encoding *)(enc))->isNmstrtMin(enc, p)) #else #define IS_NAME_CHAR_MINBPC(enc, p) (0) #define IS_NMSTRT_CHAR_MINBPC(enc, p) (0) #endif #ifdef XML_MIN_SIZE #define CHAR_MATCHES(enc, p, c) \ (((const struct normal_encoding *)(enc))->charMatches(enc, p, c)) static int sb_charMatches(const ENCODING *enc, const char *p, int c) { return *p == c; } #else /* c is an ASCII character */ #define CHAR_MATCHES(enc, p, c) (*(p) == c) #endif #define PREFIX(ident) normal_ ## ident #include "xmltok_impl.c" #undef MINBPC #undef BYTE_TYPE #undef BYTE_TO_ASCII #undef CHAR_MATCHES #undef IS_NAME_CHAR #undef IS_NAME_CHAR_MINBPC #undef IS_NMSTRT_CHAR #undef IS_NMSTRT_CHAR_MINBPC #undef IS_INVALID_CHAR enum { /* UTF8_cvalN is value of masked first byte of N byte sequence */ UTF8_cval1 = 0x00, UTF8_cval2 = 0xc0, UTF8_cval3 = 0xe0, UTF8_cval4 = 0xf0 }; static void utf8_toUtf8(const ENCODING *enc, const char **fromP, const char *fromLim, char **toP, const char *toLim) { char *to; const char *from; if (fromLim - *fromP > toLim - *toP) { /* Avoid copying partial characters. */ for (fromLim = *fromP + (toLim - *toP); fromLim > *fromP; fromLim--) if (((unsigned char)fromLim[-1] & 0xc0) != 0x80) break; } for (to = *toP, from = *fromP; from != fromLim; from++, to++) *to = *from; *fromP = from; *toP = to; } static void utf8_toUtf16(const ENCODING *enc, const char **fromP, const char *fromLim, unsigned short **toP, const unsigned short *toLim) { unsigned short *to = *toP; const char *from = *fromP; while (from != fromLim && to != toLim) { switch (((struct normal_encoding *)enc)->type[(unsigned char)*from]) { case BT_LEAD2: *to++ = ((from[0] & 0x1f) << 6) | (from[1] & 0x3f); from += 2; break; case BT_LEAD3: *to++ = ((from[0] & 0xf) << 12) | ((from[1] & 0x3f) << 6) | (from[2] & 0x3f); from += 3; break; case BT_LEAD4: { unsigned long n; if (to + 1 == toLim) break; n = ((from[0] & 0x7) << 18) | ((from[1] & 0x3f) << 12) | ((from[2] & 0x3f) << 6) | (from[3] & 0x3f); n -= 0x10000; to[0] = (unsigned short)((n >> 10) | 0xD800); to[1] = (unsigned short)((n & 0x3FF) | 0xDC00); to += 2; from += 4; } break; default: *to++ = *from++; break; } } *fromP = from; *toP = to; } #ifdef XML_NS static const struct normal_encoding utf8_encoding_ns = { { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 }, { #include "asciitab.h" #include "utf8tab.h" }, STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_) }; #endif static const struct normal_encoding utf8_encoding = { { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 }, { #define BT_COLON BT_NMSTRT #include "asciitab.h" #undef BT_COLON #include "utf8tab.h" }, STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_) }; #ifdef XML_NS static const struct normal_encoding internal_utf8_encoding_ns = { { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 }, { #include "iasciitab.h" #include "utf8tab.h" }, STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_) }; #endif static const struct normal_encoding internal_utf8_encoding = { { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 }, { #define BT_COLON BT_NMSTRT #include "iasciitab.h" #undef BT_COLON #include "utf8tab.h" }, STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_) }; static void latin1_toUtf8(const ENCODING *enc, const char **fromP, const char *fromLim, char **toP, const char *toLim) { for (;;) { unsigned char c; if (*fromP == fromLim) break; c = (unsigned char)**fromP; if (c & 0x80) { if (toLim - *toP < 2) break; *(*toP)++ = ((c >> 6) | UTF8_cval2); *(*toP)++ = ((c & 0x3f) | 0x80); (*fromP)++; } else { if (*toP == toLim) break; *(*toP)++ = *(*fromP)++; } } } static void latin1_toUtf16(const ENCODING *enc, const char **fromP, const char *fromLim, unsigned short **toP, const unsigned short *toLim) { while (*fromP != fromLim && *toP != toLim) *(*toP)++ = (unsigned char)*(*fromP)++; } #ifdef XML_NS static const struct normal_encoding latin1_encoding_ns = { { VTABLE1, latin1_toUtf8, latin1_toUtf16, 1, 0, 0 }, { #include "asciitab.h" #include "latin1tab.h" }, STANDARD_VTABLE(sb_) }; #endif static const struct normal_encoding latin1_encoding = { { VTABLE1, latin1_toUtf8, latin1_toUtf16, 1, 0, 0 }, { #define BT_COLON BT_NMSTRT #include "asciitab.h" #undef BT_COLON #include "latin1tab.h" }, STANDARD_VTABLE(sb_) }; static void ascii_toUtf8(const ENCODING *enc, const char **fromP, const char *fromLim, char **toP, const char *toLim) { while (*fromP != fromLim && *toP != toLim) *(*toP)++ = *(*fromP)++; } #ifdef XML_NS static const struct normal_encoding ascii_encoding_ns = { { VTABLE1, ascii_toUtf8, latin1_toUtf16, 1, 1, 0 }, { #include "asciitab.h" /* BT_NONXML == 0 */ }, STANDARD_VTABLE(sb_) }; #endif static const struct normal_encoding ascii_encoding = { { VTABLE1, ascii_toUtf8, latin1_toUtf16, 1, 1, 0 }, { #define BT_COLON BT_NMSTRT #include "asciitab.h" #undef BT_COLON /* BT_NONXML == 0 */ }, STANDARD_VTABLE(sb_) }; static int unicode_byte_type(char hi, char lo) { switch ((unsigned char)hi) { case 0xD8: case 0xD9: case 0xDA: case 0xDB: return BT_LEAD4; case 0xDC: case 0xDD: case 0xDE: case 0xDF: return BT_TRAIL; case 0xFF: switch ((unsigned char)lo) { case 0xFF: case 0xFE: return BT_NONXML; } break; } return BT_NONASCII; } #define DEFINE_UTF16_TO_UTF8(E) \ static \ void E ## toUtf8(const ENCODING *enc, \ const char **fromP, const char *fromLim, \ char **toP, const char *toLim) \ { \ const char *from; \ for (from = *fromP; from != fromLim; from += 2) { \ int plane; \ unsigned char lo2; \ unsigned char lo = GET_LO(from); \ unsigned char hi = GET_HI(from); \ switch (hi) { \ case 0: \ if (lo < 0x80) { \ if (*toP == toLim) { \ *fromP = from; \ return; \ } \ *(*toP)++ = lo; \ break; \ } \ /* fall through */ \ case 0x1: case 0x2: case 0x3: \ case 0x4: case 0x5: case 0x6: case 0x7: \ if (toLim - *toP < 2) { \ *fromP = from; \ return; \ } \ *(*toP)++ = ((lo >> 6) | (hi << 2) | UTF8_cval2); \ *(*toP)++ = ((lo & 0x3f) | 0x80); \ break; \ default: \ if (toLim - *toP < 3) { \ *fromP = from; \ return; \ } \ /* 16 bits divided 4, 6, 6 amongst 3 bytes */ \ *(*toP)++ = ((hi >> 4) | UTF8_cval3); \ *(*toP)++ = (((hi & 0xf) << 2) | (lo >> 6) | 0x80); \ *(*toP)++ = ((lo & 0x3f) | 0x80); \ break; \ case 0xD8: case 0xD9: case 0xDA: case 0xDB: \ if (toLim - *toP < 4) { \ *fromP = from; \ return; \ } \ plane = (((hi & 0x3) << 2) | ((lo >> 6) & 0x3)) + 1; \ *(*toP)++ = ((plane >> 2) | UTF8_cval4); \ *(*toP)++ = (((lo >> 2) & 0xF) | ((plane & 0x3) << 4) | 0x80); \ from += 2; \ lo2 = GET_LO(from); \ *(*toP)++ = (((lo & 0x3) << 4) \ | ((GET_HI(from) & 0x3) << 2) \ | (lo2 >> 6) \ | 0x80); \ *(*toP)++ = ((lo2 & 0x3f) | 0x80); \ break; \ } \ } \ *fromP = from; \ } #define DEFINE_UTF16_TO_UTF16(E) \ static \ void E ## toUtf16(const ENCODING *enc, \ const char **fromP, const char *fromLim, \ unsigned short **toP, const unsigned short *toLim) \ { \ /* Avoid copying first half only of surrogate */ \ if (fromLim - *fromP > ((toLim - *toP) << 1) \ && (GET_HI(fromLim - 2) & 0xF8) == 0xD8) \ fromLim -= 2; \ for (; *fromP != fromLim && *toP != toLim; *fromP += 2) \ *(*toP)++ = (GET_HI(*fromP) << 8) | GET_LO(*fromP); \ } #define SET2(ptr, ch) \ (((ptr)[0] = ((ch) & 0xff)), ((ptr)[1] = ((ch) >> 8))) #define GET_LO(ptr) ((unsigned char)(ptr)[0]) #define GET_HI(ptr) ((unsigned char)(ptr)[1]) DEFINE_UTF16_TO_UTF8(little2_) DEFINE_UTF16_TO_UTF16(little2_) #undef SET2 #undef GET_LO #undef GET_HI #define SET2(ptr, ch) \ (((ptr)[0] = ((ch) >> 8)), ((ptr)[1] = ((ch) & 0xFF))) #define GET_LO(ptr) ((unsigned char)(ptr)[1]) #define GET_HI(ptr) ((unsigned char)(ptr)[0]) DEFINE_UTF16_TO_UTF8(big2_) DEFINE_UTF16_TO_UTF16(big2_) #undef SET2 #undef GET_LO #undef GET_HI #define LITTLE2_BYTE_TYPE(enc, p) \ ((p)[1] == 0 \ ? ((struct normal_encoding *)(enc))->type[(unsigned char)*(p)] \ : unicode_byte_type((p)[1], (p)[0])) #define LITTLE2_BYTE_TO_ASCII(enc, p) ((p)[1] == 0 ? (p)[0] : -1) #define LITTLE2_CHAR_MATCHES(enc, p, c) ((p)[1] == 0 && (p)[0] == c) #define LITTLE2_IS_NAME_CHAR_MINBPC(enc, p) \ UCS2_GET_NAMING(namePages, (unsigned char)p[1], (unsigned char)p[0]) #define LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p) \ UCS2_GET_NAMING(nmstrtPages, (unsigned char)p[1], (unsigned char)p[0]) #ifdef XML_MIN_SIZE static int little2_byteType(const ENCODING *enc, const char *p) { return LITTLE2_BYTE_TYPE(enc, p); } static int little2_byteToAscii(const ENCODING *enc, const char *p) { return LITTLE2_BYTE_TO_ASCII(enc, p); } static int little2_charMatches(const ENCODING *enc, const char *p, int c) { return LITTLE2_CHAR_MATCHES(enc, p, c); } static int little2_isNameMin(const ENCODING *enc, const char *p) { return LITTLE2_IS_NAME_CHAR_MINBPC(enc, p); } static int little2_isNmstrtMin(const ENCODING *enc, const char *p) { return LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p); } #undef VTABLE #define VTABLE VTABLE1, little2_toUtf8, little2_toUtf16 #else /* not XML_MIN_SIZE */ #undef PREFIX #define PREFIX(ident) little2_ ## ident #define MINBPC(enc) 2 /* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */ #define BYTE_TYPE(enc, p) LITTLE2_BYTE_TYPE(enc, p) #define BYTE_TO_ASCII(enc, p) LITTLE2_BYTE_TO_ASCII(enc, p) #define CHAR_MATCHES(enc, p, c) LITTLE2_CHAR_MATCHES(enc, p, c) #define IS_NAME_CHAR(enc, p, n) 0 #define IS_NAME_CHAR_MINBPC(enc, p) LITTLE2_IS_NAME_CHAR_MINBPC(enc, p) #define IS_NMSTRT_CHAR(enc, p, n) (0) #define IS_NMSTRT_CHAR_MINBPC(enc, p) LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p) #include "xmltok_impl.c" #undef MINBPC #undef BYTE_TYPE #undef BYTE_TO_ASCII #undef CHAR_MATCHES #undef IS_NAME_CHAR #undef IS_NAME_CHAR_MINBPC #undef IS_NMSTRT_CHAR #undef IS_NMSTRT_CHAR_MINBPC #undef IS_INVALID_CHAR #endif /* not XML_MIN_SIZE */ #ifdef XML_NS static const struct normal_encoding little2_encoding_ns = { { VTABLE, 2, 0, #if XML_BYTE_ORDER == 12 1 #else 0 #endif }, { #include "asciitab.h" #include "latin1tab.h" }, STANDARD_VTABLE(little2_) }; #endif static const struct normal_encoding little2_encoding = { { VTABLE, 2, 0, #if XML_BYTE_ORDER == 12 1 #else 0 #endif }, { #define BT_COLON BT_NMSTRT #include "asciitab.h" #undef BT_COLON #include "latin1tab.h" }, STANDARD_VTABLE(little2_) }; #if XML_BYTE_ORDER != 21 #ifdef XML_NS static const struct normal_encoding internal_little2_encoding_ns = { { VTABLE, 2, 0, 1 }, { #include "iasciitab.h" #include "latin1tab.h" }, STANDARD_VTABLE(little2_) }; #endif static const struct normal_encoding internal_little2_encoding = { { VTABLE, 2, 0, 1 }, { #define BT_COLON BT_NMSTRT #include "iasciitab.h" #undef BT_COLON #include "latin1tab.h" }, STANDARD_VTABLE(little2_) }; #endif #define BIG2_BYTE_TYPE(enc, p) \ ((p)[0] == 0 \ ? ((struct normal_encoding *)(enc))->type[(unsigned char)(p)[1]] \ : unicode_byte_type((p)[0], (p)[1])) #define BIG2_BYTE_TO_ASCII(enc, p) ((p)[0] == 0 ? (p)[1] : -1) #define BIG2_CHAR_MATCHES(enc, p, c) ((p)[0] == 0 && (p)[1] == c) #define BIG2_IS_NAME_CHAR_MINBPC(enc, p) \ UCS2_GET_NAMING(namePages, (unsigned char)p[0], (unsigned char)p[1]) #define BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p) \ UCS2_GET_NAMING(nmstrtPages, (unsigned char)p[0], (unsigned char)p[1]) #ifdef XML_MIN_SIZE static int big2_byteType(const ENCODING *enc, const char *p) { return BIG2_BYTE_TYPE(enc, p); } static int big2_byteToAscii(const ENCODING *enc, const char *p) { return BIG2_BYTE_TO_ASCII(enc, p); } static int big2_charMatches(const ENCODING *enc, const char *p, int c) { return BIG2_CHAR_MATCHES(enc, p, c); } static int big2_isNameMin(const ENCODING *enc, const char *p) { return BIG2_IS_NAME_CHAR_MINBPC(enc, p); } static int big2_isNmstrtMin(const ENCODING *enc, const char *p) { return BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p); } #undef VTABLE #define VTABLE VTABLE1, big2_toUtf8, big2_toUtf16 #else /* not XML_MIN_SIZE */ #undef PREFIX #define PREFIX(ident) big2_ ## ident #define MINBPC(enc) 2 /* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */ #define BYTE_TYPE(enc, p) BIG2_BYTE_TYPE(enc, p) #define BYTE_TO_ASCII(enc, p) BIG2_BYTE_TO_ASCII(enc, p) #define CHAR_MATCHES(enc, p, c) BIG2_CHAR_MATCHES(enc, p, c) #define IS_NAME_CHAR(enc, p, n) 0 #define IS_NAME_CHAR_MINBPC(enc, p) BIG2_IS_NAME_CHAR_MINBPC(enc, p) #define IS_NMSTRT_CHAR(enc, p, n) (0) #define IS_NMSTRT_CHAR_MINBPC(enc, p) BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p) #include "xmltok_impl.c" #undef MINBPC #undef BYTE_TYPE #undef BYTE_TO_ASCII #undef CHAR_MATCHES #undef IS_NAME_CHAR #undef IS_NAME_CHAR_MINBPC #undef IS_NMSTRT_CHAR #undef IS_NMSTRT_CHAR_MINBPC #undef IS_INVALID_CHAR #endif /* not XML_MIN_SIZE */ #ifdef XML_NS static const struct normal_encoding big2_encoding_ns = { { VTABLE, 2, 0, #if XML_BYTE_ORDER == 21 1 #else 0 #endif }, { #include "asciitab.h" #include "latin1tab.h" }, STANDARD_VTABLE(big2_) }; #endif static const struct normal_encoding big2_encoding = { { VTABLE, 2, 0, #if XML_BYTE_ORDER == 21 1 #else 0 #endif }, { #define BT_COLON BT_NMSTRT #include "asciitab.h" #undef BT_COLON #include "latin1tab.h" }, STANDARD_VTABLE(big2_) }; #if XML_BYTE_ORDER != 12 #ifdef XML_NS static const struct normal_encoding internal_big2_encoding_ns = { { VTABLE, 2, 0, 1 }, { #include "iasciitab.h" #include "latin1tab.h" }, STANDARD_VTABLE(big2_) }; #endif static const struct normal_encoding internal_big2_encoding = { { VTABLE, 2, 0, 1 }, { #define BT_COLON BT_NMSTRT #include "iasciitab.h" #undef BT_COLON #include "latin1tab.h" }, STANDARD_VTABLE(big2_) }; #endif #undef PREFIX static int streqci(const char *s1, const char *s2) { for (;;) { char c1 = *s1++; char c2 = *s2++; if (ASCII_a <= c1 && c1 <= ASCII_z) c1 += ASCII_A - ASCII_a; if (ASCII_a <= c2 && c2 <= ASCII_z) c2 += ASCII_A - ASCII_a; if (c1 != c2) return 0; if (!c1) break; } return 1; } static void initUpdatePosition(const ENCODING *enc, const char *ptr, const char *end, POSITION *pos) { normal_updatePosition(&utf8_encoding.enc, ptr, end, pos); } static int toAscii(const ENCODING *enc, const char *ptr, const char *end) { char buf[1]; char *p = buf; XmlUtf8Convert(enc, &ptr, end, &p, p + 1); if (p == buf) return -1; else return buf[0]; } static int isSpace(int c) { switch (c) { case 0x20: case 0xD: case 0xA: case 0x9: return 1; } return 0; } /* Return 1 if there's just optional white space or there's an S followed by name=val. */ static int parsePseudoAttribute(const ENCODING *enc, const char *ptr, const char *end, const char **namePtr, const char **nameEndPtr, const char **valPtr, const char **nextTokPtr) { int c; char open; if (ptr == end) { *namePtr = 0; return 1; } if (!isSpace(toAscii(enc, ptr, end))) { *nextTokPtr = ptr; return 0; } do { ptr += enc->minBytesPerChar; } while (isSpace(toAscii(enc, ptr, end))); if (ptr == end) { *namePtr = 0; return 1; } *namePtr = ptr; for (;;) { c = toAscii(enc, ptr, end); if (c == -1) { *nextTokPtr = ptr; return 0; } if (c == ASCII_EQUALS) { *nameEndPtr = ptr; break; } if (isSpace(c)) { *nameEndPtr = ptr; do { ptr += enc->minBytesPerChar; } while (isSpace(c = toAscii(enc, ptr, end))); if (c != ASCII_EQUALS) { *nextTokPtr = ptr; return 0; } break; } ptr += enc->minBytesPerChar; } if (ptr == *namePtr) { *nextTokPtr = ptr; return 0; } ptr += enc->minBytesPerChar; c = toAscii(enc, ptr, end); while (isSpace(c)) { ptr += enc->minBytesPerChar; c = toAscii(enc, ptr, end); } if (c != ASCII_QUOT && c != ASCII_APOS) { *nextTokPtr = ptr; return 0; } open = c; ptr += enc->minBytesPerChar; *valPtr = ptr; for (;; ptr += enc->minBytesPerChar) { c = toAscii(enc, ptr, end); if (c == open) break; if (!(ASCII_a <= c && c <= ASCII_z) && !(ASCII_A <= c && c <= ASCII_Z) && !(ASCII_0 <= c && c <= ASCII_9) && c != ASCII_PERIOD && c != ASCII_MINUS && c != ASCII_UNDERSCORE) { *nextTokPtr = ptr; return 0; } } *nextTokPtr = ptr + enc->minBytesPerChar; return 1; } static const char KW_version[] = { ASCII_v, ASCII_e, ASCII_r, ASCII_s, ASCII_i, ASCII_o, ASCII_n, '\0' }; static const char KW_encoding[] = { ASCII_e, ASCII_n, ASCII_c, ASCII_o, ASCII_d, ASCII_i, ASCII_n, ASCII_g, '\0' }; static const char KW_standalone[] = { ASCII_s, ASCII_t, ASCII_a, ASCII_n, ASCII_d, ASCII_a, ASCII_l, ASCII_o, ASCII_n, ASCII_e, '\0' }; static const char KW_yes[] = { ASCII_y, ASCII_e, ASCII_s, '\0' }; static const char KW_no[] = { ASCII_n, ASCII_o, '\0' }; static int doParseXmlDecl(const ENCODING *(*encodingFinder)(const ENCODING *, const char *, const char *), int isGeneralTextEntity, const ENCODING *enc, const char *ptr, const char *end, const char **badPtr, const char **versionPtr, const char **encodingName, const ENCODING **encoding, int *standalone) { const char *val = 0; const char *name = 0; const char *nameEnd = 0; ptr += 5 * enc->minBytesPerChar; end -= 2 * enc->minBytesPerChar; if (!parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr) || !name) { *badPtr = ptr; return 0; } if (!XmlNameMatchesAscii(enc, name, nameEnd, KW_version)) { if (!isGeneralTextEntity) { *badPtr = name; return 0; } } else { if (versionPtr) *versionPtr = val; if (!parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr)) { *badPtr = ptr; return 0; } if (!name) { if (isGeneralTextEntity) { /* a TextDecl must have an EncodingDecl */ *badPtr = ptr; return 0; } return 1; } } if (XmlNameMatchesAscii(enc, name, nameEnd, KW_encoding)) { int c = toAscii(enc, val, end); if (!(ASCII_a <= c && c <= ASCII_z) && !(ASCII_A <= c && c <= ASCII_Z)) { *badPtr = val; return 0; } if (encodingName) *encodingName = val; if (encoding) *encoding = encodingFinder(enc, val, ptr - enc->minBytesPerChar); if (!parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr)) { *badPtr = ptr; return 0; } if (!name) return 1; } if (!XmlNameMatchesAscii(enc, name, nameEnd, KW_standalone) || isGeneralTextEntity) { *badPtr = name; return 0; } if (XmlNameMatchesAscii(enc, val, ptr - enc->minBytesPerChar, KW_yes)) { if (standalone) *standalone = 1; } else if (XmlNameMatchesAscii(enc, val, ptr - enc->minBytesPerChar, KW_no)) { if (standalone) *standalone = 0; } else { *badPtr = val; return 0; } while (isSpace(toAscii(enc, ptr, end))) ptr += enc->minBytesPerChar; if (ptr != end) { *badPtr = ptr; return 0; } return 1; } static int checkCharRefNumber(int result) { switch (result >> 8) { case 0xD8: case 0xD9: case 0xDA: case 0xDB: case 0xDC: case 0xDD: case 0xDE: case 0xDF: return -1; case 0: if (latin1_encoding.type[result] == BT_NONXML) return -1; break; case 0xFF: if (result == 0xFFFE || result == 0xFFFF) return -1; break; } return result; } int XmlUtf8Encode(int c, char *buf) { enum { /* minN is minimum legal resulting value for N byte sequence */ min2 = 0x80, min3 = 0x800, min4 = 0x10000 }; if (c < 0) return 0; if (c < min2) { buf[0] = (c | UTF8_cval1); return 1; } if (c < min3) { buf[0] = ((c >> 6) | UTF8_cval2); buf[1] = ((c & 0x3f) | 0x80); return 2; } if (c < min4) { buf[0] = ((c >> 12) | UTF8_cval3); buf[1] = (((c >> 6) & 0x3f) | 0x80); buf[2] = ((c & 0x3f) | 0x80); return 3; } if (c < 0x110000) { buf[0] = ((c >> 18) | UTF8_cval4); buf[1] = (((c >> 12) & 0x3f) | 0x80); buf[2] = (((c >> 6) & 0x3f) | 0x80); buf[3] = ((c & 0x3f) | 0x80); return 4; } return 0; } int XmlUtf16Encode(int charNum, unsigned short *buf) { if (charNum < 0) return 0; if (charNum < 0x10000) { buf[0] = charNum; return 1; } if (charNum < 0x110000) { charNum -= 0x10000; buf[0] = (charNum >> 10) + 0xD800; buf[1] = (charNum & 0x3FF) + 0xDC00; return 2; } return 0; } struct unknown_encoding { struct normal_encoding normal; int (*convert)(void *userData, const char *p); void *userData; unsigned short utf16[256]; char utf8[256][4]; }; int XmlSizeOfUnknownEncoding(void) { return sizeof(struct unknown_encoding); } static int unknown_isName(const ENCODING *enc, const char *p) { int c = ((const struct unknown_encoding *)enc) ->convert(((const struct unknown_encoding *)enc)->userData, p); if (c & ~0xFFFF) return 0; return UCS2_GET_NAMING(namePages, c >> 8, c & 0xFF); } static int unknown_isNmstrt(const ENCODING *enc, const char *p) { int c = ((const struct unknown_encoding *)enc) ->convert(((const struct unknown_encoding *)enc)->userData, p); if (c & ~0xFFFF) return 0; return UCS2_GET_NAMING(nmstrtPages, c >> 8, c & 0xFF); } static int unknown_isInvalid(const ENCODING *enc, const char *p) { int c = ((const struct unknown_encoding *)enc) ->convert(((const struct unknown_encoding *)enc)->userData, p); return (c & ~0xFFFF) || checkCharRefNumber(c) < 0; } static void unknown_toUtf8(const ENCODING *enc, const char **fromP, const char *fromLim, char **toP, const char *toLim) { char buf[XML_UTF8_ENCODE_MAX]; for (;;) { const char *utf8; int n; if (*fromP == fromLim) break; utf8 = ((const struct unknown_encoding *)enc)->utf8[(unsigned char)**fromP]; n = *utf8++; if (n == 0) { int c = ((const struct unknown_encoding *)enc) ->convert(((const struct unknown_encoding *)enc)->userData, *fromP); n = XmlUtf8Encode(c, buf); if (n > toLim - *toP) break; utf8 = buf; *fromP += ((const struct normal_encoding *)enc)->type[(unsigned char)**fromP] - (BT_LEAD2 - 2); } else { if (n > toLim - *toP) break; (*fromP)++; } do { *(*toP)++ = *utf8++; } while (--n != 0); } } static void unknown_toUtf16(const ENCODING *enc, const char **fromP, const char *fromLim, unsigned short **toP, const unsigned short *toLim) { while (*fromP != fromLim && *toP != toLim) { unsigned short c = ((const struct unknown_encoding *)enc)->utf16[(unsigned char)**fromP]; if (c == 0) { c = (unsigned short)((const struct unknown_encoding *)enc) ->convert(((const struct unknown_encoding *)enc)->userData, *fromP); *fromP += ((const struct normal_encoding *)enc)->type[(unsigned char)**fromP] - (BT_LEAD2 - 2); } else (*fromP)++; *(*toP)++ = c; } } ENCODING * XmlInitUnknownEncoding(void *mem, int *table, int (*convert)(void *userData, const char *p), void *userData) { int i; struct unknown_encoding *e = mem; for (i = 0; i < (int)sizeof(struct normal_encoding); i++) ((char *)mem)[i] = ((char *)&latin1_encoding)[i]; for (i = 0; i < 128; i++) if (latin1_encoding.type[i] != BT_OTHER && latin1_encoding.type[i] != BT_NONXML && table[i] != i) return 0; for (i = 0; i < 256; i++) { int c = table[i]; if (c == -1) { e->normal.type[i] = BT_MALFORM; /* This shouldn't really get used. */ e->utf16[i] = 0xFFFF; e->utf8[i][0] = 1; e->utf8[i][1] = 0; } else if (c < 0) { if (c < -4) return 0; e->normal.type[i] = BT_LEAD2 - (c + 2); e->utf8[i][0] = 0; e->utf16[i] = 0; } else if (c < 0x80) { if (latin1_encoding.type[c] != BT_OTHER && latin1_encoding.type[c] != BT_NONXML && c != i) return 0; e->normal.type[i] = latin1_encoding.type[c]; e->utf8[i][0] = 1; e->utf8[i][1] = (char)c; e->utf16[i] = c == 0 ? 0xFFFF : c; } else if (checkCharRefNumber(c) < 0) { e->normal.type[i] = BT_NONXML; /* This shouldn't really get used. */ e->utf16[i] = 0xFFFF; e->utf8[i][0] = 1; e->utf8[i][1] = 0; } else { if (c > 0xFFFF) return 0; if (UCS2_GET_NAMING(nmstrtPages, c >> 8, c & 0xff)) e->normal.type[i] = BT_NMSTRT; else if (UCS2_GET_NAMING(namePages, c >> 8, c & 0xff)) e->normal.type[i] = BT_NAME; else e->normal.type[i] = BT_OTHER; e->utf8[i][0] = (char)XmlUtf8Encode(c, e->utf8[i] + 1); e->utf16[i] = c; } } e->userData = userData; e->convert = convert; if (convert) { e->normal.isName2 = unknown_isName; e->normal.isName3 = unknown_isName; e->normal.isName4 = unknown_isName; e->normal.isNmstrt2 = unknown_isNmstrt; e->normal.isNmstrt3 = unknown_isNmstrt; e->normal.isNmstrt4 = unknown_isNmstrt; e->normal.isInvalid2 = unknown_isInvalid; e->normal.isInvalid3 = unknown_isInvalid; e->normal.isInvalid4 = unknown_isInvalid; } e->normal.enc.utf8Convert = unknown_toUtf8; e->normal.enc.utf16Convert = unknown_toUtf16; return &(e->normal.enc); } /* If this enumeration is changed, getEncodingIndex and encodings must also be changed. */ enum { UNKNOWN_ENC = -1, ISO_8859_1_ENC = 0, US_ASCII_ENC, UTF_8_ENC, UTF_16_ENC, UTF_16BE_ENC, UTF_16LE_ENC, /* must match encodingNames up to here */ NO_ENC }; static const char KW_ISO_8859_1[] = { ASCII_I, ASCII_S, ASCII_O, ASCII_MINUS, ASCII_8, ASCII_8, ASCII_5, ASCII_9, ASCII_MINUS, ASCII_1, '\0' }; static const char KW_US_ASCII[] = { ASCII_U, ASCII_S, ASCII_MINUS, ASCII_A, ASCII_S, ASCII_C, ASCII_I, ASCII_I, '\0' }; static const char KW_UTF_8[] = { ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_8, '\0' }; static const char KW_UTF_16[] = { ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1, ASCII_6, '\0' }; static const char KW_UTF_16BE[] = { ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1, ASCII_6, ASCII_B, ASCII_E, '\0' }; static const char KW_UTF_16LE[] = { ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1, ASCII_6, ASCII_L, ASCII_E, '\0' }; static int getEncodingIndex(const char *name) { static const char *encodingNames[] = { KW_ISO_8859_1, KW_US_ASCII, KW_UTF_8, KW_UTF_16, KW_UTF_16BE, KW_UTF_16LE, }; int i; if (name == 0) return NO_ENC; for (i = 0; i < (int)(sizeof(encodingNames)/sizeof(encodingNames[0])); i++) if (streqci(name, encodingNames[i])) return i; return UNKNOWN_ENC; } /* For binary compatibility, we store the index of the encoding specified at initialization in the isUtf16 member. */ #define INIT_ENC_INDEX(enc) ((int)(enc)->initEnc.isUtf16) #define SET_INIT_ENC_INDEX(enc, i) ((enc)->initEnc.isUtf16 = (char)i) /* This is what detects the encoding. encodingTable maps from encoding indices to encodings; INIT_ENC_INDEX(enc) is the index of the external (protocol) specified encoding; state is XML_CONTENT_STATE if we're parsing an external text entity, and XML_PROLOG_STATE otherwise. */ static int initScan(const ENCODING **encodingTable, const INIT_ENCODING *enc, int state, const char *ptr, const char *end, const char **nextTokPtr) { const ENCODING **encPtr; if (ptr == end) return XML_TOK_NONE; encPtr = enc->encPtr; if (ptr + 1 == end) { /* only a single byte available for auto-detection */ #ifndef XML_DTD /* FIXME */ /* a well-formed document entity must have more than one byte */ if (state != XML_CONTENT_STATE) return XML_TOK_PARTIAL; #endif /* so we're parsing an external text entity... */ /* if UTF-16 was externally specified, then we need at least 2 bytes */ switch (INIT_ENC_INDEX(enc)) { case UTF_16_ENC: case UTF_16LE_ENC: case UTF_16BE_ENC: return XML_TOK_PARTIAL; } switch ((unsigned char)*ptr) { case 0xFE: case 0xFF: case 0xEF: /* possibly first byte of UTF-8 BOM */ if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC && state == XML_CONTENT_STATE) break; /* fall through */ case 0x00: case 0x3C: return XML_TOK_PARTIAL; } } else { switch (((unsigned char)ptr[0] << 8) | (unsigned char)ptr[1]) { case 0xFEFF: if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC && state == XML_CONTENT_STATE) break; *nextTokPtr = ptr + 2; *encPtr = encodingTable[UTF_16BE_ENC]; return XML_TOK_BOM; /* 00 3C is handled in the default case */ case 0x3C00: if ((INIT_ENC_INDEX(enc) == UTF_16BE_ENC || INIT_ENC_INDEX(enc) == UTF_16_ENC) && state == XML_CONTENT_STATE) break; *encPtr = encodingTable[UTF_16LE_ENC]; return XmlTok(*encPtr, state, ptr, end, nextTokPtr); case 0xFFFE: if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC && state == XML_CONTENT_STATE) break; *nextTokPtr = ptr + 2; *encPtr = encodingTable[UTF_16LE_ENC]; return XML_TOK_BOM; case 0xEFBB: /* Maybe a UTF-8 BOM (EF BB BF) */ /* If there's an explicitly specified (external) encoding of ISO-8859-1 or some flavour of UTF-16 and this is an external text entity, don't look for the BOM, because it might be a legal data. */ if (state == XML_CONTENT_STATE) { int e = INIT_ENC_INDEX(enc); if (e == ISO_8859_1_ENC || e == UTF_16BE_ENC || e == UTF_16LE_ENC || e == UTF_16_ENC) break; } if (ptr + 2 == end) return XML_TOK_PARTIAL; if ((unsigned char)ptr[2] == 0xBF) { *encPtr = encodingTable[UTF_8_ENC]; return XML_TOK_BOM; } break; default: if (ptr[0] == '\0') { /* 0 isn't a legal data character. Furthermore a document entity can only start with ASCII characters. So the only way this can fail to be big-endian UTF-16 if it it's an external parsed general entity that's labelled as UTF-16LE. */ if (state == XML_CONTENT_STATE && INIT_ENC_INDEX(enc) == UTF_16LE_ENC) break; *encPtr = encodingTable[UTF_16BE_ENC]; return XmlTok(*encPtr, state, ptr, end, nextTokPtr); } else if (ptr[1] == '\0') { /* We could recover here in the case: - parsing an external entity - second byte is 0 - no externally specified encoding - no encoding declaration by assuming UTF-16LE. But we don't, because this would mean when presented just with a single byte, we couldn't reliably determine whether we needed further bytes. */ if (state == XML_CONTENT_STATE) break; *encPtr = encodingTable[UTF_16LE_ENC]; return XmlTok(*encPtr, state, ptr, end, nextTokPtr); } break; } } *encPtr = encodingTable[INIT_ENC_INDEX(enc)]; return XmlTok(*encPtr, state, ptr, end, nextTokPtr); } #define NS(x) x #define ns(x) x #include "xmltok_ns.c" #undef NS #undef ns #ifdef XML_NS #define NS(x) x ## NS #define ns(x) x ## _ns #include "xmltok_ns.c" #undef NS #undef ns ENCODING * XmlInitUnknownEncodingNS(void *mem, int *table, int (*convert)(void *userData, const char *p), void *userData) { ENCODING *enc = XmlInitUnknownEncoding(mem, table, convert, userData); if (enc) ((struct normal_encoding *)enc)->type[ASCII_COLON] = BT_COLON; return enc; } #endif /* XML_NS */ matanza-0.13/mmp.h0000644000175000017500000004104507250210244014202 0ustar boradminboradmin// MATANZA MACHINE MMP - MMP // // This is the master file for the MMP. It is formatted as a C header file to // make it possible to include it into C programs, but it contains the whole // documentation on how to implement a compliant server/client. // // It should be noted that the MMP is currently in development stage and is // very likely to change in the future. Keep that in mind when developing your // clients. Whenever a new change to this specification is added, it will be // documented at the end of this file. Look there if you were already familiar // with MMP and just want to see what has changed. // // MMP is the protocol Matanza servers and clients talk. It is being designed // with the following goals: // // 1. Making it possible to use Matanza proxies, reducing the bandwidth at the // server. That should help it scale very much. // // 2. Making it possible to implement artificial inteligence to run outside of // the Matanza process. This way, multiple implementations of artificial // inteligence might be connected to the same server, regardless of the // programming languages they were written on. // // 3. Help others implement different clients to the Matanza game. Specially, // Sergio Garcia, who said he would soon begin to work on a graphical // Java-based client. // // MMP has not been designed to be human-readable. Doing so would increase the // bandwidth required by MMP-talking programs. // // On the other hand, one of the design goals of MMP was that it should be // fairly easy to implement a MMP-speaking program. This means that it doesn't // use any complicated compression algorithms of any sort. // // As you will see, it is possible to control multiple ships in multiple // universes (once multiple universes gets supported in Matanza) using only one // connection. This adds little complexity, but makes it possible to have // multiple clients connected to one proxy, having that proxy use only one // connection to the central server. // // In this initial version of MMP, TCP/IP connections are used. However, it // should be noted that there is many information that should be sent over UDP // rather than TCP (while it is important to send other using TCP). In the // future, two programs talking MMP will probably use both one TCP connection // for important messages and one UDP connection for the rest. For example, // information about the positions of the objects is better sent over UDP, // while messages such as the fact that a given ship controled by the client // has been hit should be sent over TCP. We are aiming at making this work // completely over TCP first, avoiding the complexity of using both TCP and // UDP, to eventually start sending messages through the appropriate channel. // // All the messages in MMP begin with a single character, followed by any // relevant arguments. Basically, both the server and the client are at // special defined states and the messages they may receive depend on this // information. // // In MMP, unless said otherwise, all numbers are sent as two bytes, the first // being the most important (for example, the number 12345 would be sent as the // numbers 48 and 57, since 48 * 256 + 57 = 12345). Strings are sent as // 0-terminated strings. For example, to send the string "ABC", one would send // the numbers 65 (`A'), 66 (`B'), 67 (`C') and 0. // // The messages designed to be sent by the server have been prefixed with // `MMP_SERVER_'. Those sent by the client begin with `MMP_CLIENT_'. They // have been grouped depending on the state on which they are allowed. // // We will first describe the messages sent by the server and then those sent // by the clients. // // The initial states for both servers and clients once a connection is // established is Initial. // FUNCTIONALITY STILL MISSING IN MMP // // As said above, MMP is still undergoing heavy development. As you will see, // there are some things that are not yet possible to do with the current // specification. // // The following is provided as a list of things that you will be able to do // with MMP, but not yet. // // - Add support for teams // // None of the messages has the concept of teams. It should be possible to // play with teams. // // - Add chat functionality // // It should be possible to send public and private messages through MMP. // // - Allow the client to control the ships // // In the current specification, the client has no way to specify actions // for the ships it controls. // // - Complete this list // // There are still a few things missing, that we must add to the list. If // you come up with any, email Alejandro so he adds it. // MESSAGES SENT BY THE SERVER // // The following messages can be sent by the server when the client is in the // Initial state (that is, right after the connection is established). // // Actually, the server will wait for a MMP_CLIENT_INITIAL_ID before sending // any of these replies. #define MMP_SERVER_CLOSE 0 // MMP_SERVER_CLOSE // // An error took place at the server. The client's state is set to // Close. #define MMP_SERVER_INITIAL_FULL 1 // MMP_SERVER_INITIAL_FULL // // Indicates that the server is currently full. The client should try to // connect latter. The server must close the connection after sending // this message. #define MMP_SERVER_INITIAL_CONNECTED 2 // MMP_SERVER_INITIAL_CONNECTED // // Indicates that the operation was successful and sets the client on the // Default state. This message contains two strings used to identify the // server. The first is the server's name (such as "MatanzaServer") and // the second is its version (such as "0.11"). // // A server can only send this message after MMP_CLIENT_INITIAL_ID has // been received. // The following messages can be sent by the server when the client is in the // Default state: // MMP_SERVER_CLOSE // // This message indicates that the server is about to close the // connection. The client enters the Close state. #define MMP_SERVER_DEFAULT_FRAME_SHIPS 100 // MMP_SERVER_DEFAULT_FRAME_SHIPS // // The server uses this message to begin sending information about one of // the universes that the client is subscribed to. // // A simple frame contains the whole information about the state of the // world. // // This message has two arguments. The first is the id of the universe // it will begin to update. The second argument is a vector with the // following information for every ship on that universe: // // pos_x - The position of the ship in the X coordinate. // pos_y - The position of the ship in the Y coordinate. // ang - The current angle of the ship. // // The client must know how many ships every universe has and how they // are ordered. // // This message sets the client's state to Frame. #define MMP_SERVER_DEFAULT_SHIPADD_CLIENT 2 // MMP_SERVER_DEFAULT_SHIPADD_CLIENT // // This message is sent by the server when the client succesfully adds a // ship to a universe. The message has the ship's id (a number) as its // arguments. // // For every MMP_CLIENT_DEFAULT_SHIPADD request, the server will // reply with either a MMP_SERVER_DEFAULT_SHIPADD_CLIENT or a // MMP_SERVER_DEFAULT_SHIPADD_FAILURE message. This replies will be // sent in the same order as the MMP_CLIENT_DEFAULT_SHIPADD requests // are received. // // The new ship is added at the beginning of the list of ships for the // universe. Note that the order of this list is the same as used for // the arguments to the MMP_SERVER_DEFAULT_FRAME_SHIPS message. // // See MMP_CLIENT_DEFAULT_SHIPADD for more information. #define MMP_SERVER_DEFAULT_SHIPADD_FAIL 3 // MMP_SERVER_DEFAULT_SHIPADD_FAIL // // If an attempt to add a ship to a universe (indicated by the client // sending a MMP_CLIENT_DEFAULT_SHIPADD message) fails, the server // will send this reply. The client enters the ShipAddFailure state. #define MMP_SERVER_DEFAULT_SHIPADD_OTHER 4 // MMP_SERVER_DEFAULT_SHIPADD_OTHER // // This message is sent by the server to notify the client that someone // else has added a ship to one of the universes' the client is // subscribed to. // // The new ship is added at the beginning of the list of ships for the // universe. Note that the order of this list is the same as used for // the arguments to the MMP_SERVER_DEFAULT_FRAME_SHIPS message. // // The message has the universe id (number) and the player's name // (string) as its arguments. #define MMP_SERVER_DEFAULT_DAMAGE 5 // MMP_SERVER_DEFAULT_DAMAGE // // Whenever one of the ships controled by the client is damaged, the // server will send this message. The argument is a number with the // ammount of damage. It is the clients' responsability to keep track of // its ships' damage to know when they are finally destroyed. // #define MMP_SERVER_DEFAULT_JOIN_OK 6 // MMP_SERVER_DEFAULT_JOIN_OK // // This message does not modified the client's state. // // It is sent by the server as a reply to a MMP_CLIENT_DEFAULT_JOIN // that resulted in a successful subscription to a universe. The message // has a list with the names for all the ships currently in the universe // as its only argument. Finally, when no more ships are left, it sends // an empty string. // // Note that the order of the ships is relevant as it is in this order // that their information will be sent in MMP_SERVER_DEFAULT_FRAME_SHIPS. // // See MMP_CLIENT_DEFAULT_JOIN for more information. #define MMP_SERVER_DEFAULT_JOIN_FAIL 7 // MMP_SERVER_DEFAULT_JOIN_FAIL // // This message indicates that an attempt to subscribe to a universe // (sent by the client using the MMP_CLIENT_DEFAULT_JOIN message) // failed. The client is then set on the JoinFailure state. #define MMP_SERVER_DEFAULT_SHIPRM 8 // MMP_SERVER_DEFAULT_SHIPRM // // This message is used by the server to inform the client that a // particular ship in a given universe has left. The client's state is // not modified, but it should record the change in the list of ships for // the universe, as further MMP_SERVER_DEFAULT_FRAME_SHIPS messages will // not contain any information for the ship. // // The message's arguments are the universe's id (two bytes) and the // ship's name. // The following messages are sent when the client is in the JoinFailure state. // They are used by the server to indicate the reasons why the request failed. // All of them set the client's state to the Default: #define MMP_SERVER_JOINFAIL_UNEXISTANT 0 // MMP_SERVER_JOINFAIL_UNEXISTANT // // This message is sent when the client attempts to join to a universe // that does not exist. #define MMP_SERVER_JOINFAIL_AUTH 1 // MMP_SERVER_JOINFAIL_AUTH // // This message will be defined in the future. // // The following messages are valid when the client is in the ShipAddFailure // state. They all bring the client back to the Default state. #define MMP_SERVER_SHIPADDFAIL_UNEXISTANT 1 // MMP_SERVER_SHIPADDFAIL_UNEXISTANT // // The universe specified does not exist. #define MMP_SERVER_SHIPADDFAIL_FULL 2 // MMP_SERVER_SHIPADDFAIL_FULL #define MMP_SERVER_SHIPADDFAIL_BADNAME 3 // MMP_SERVER_SHIPADDFAIL_BADNAME // // This error happens when the name for the ship has problems. A string // describing the error with the name specified is sent. // // The following are the messages that the client can receive during the Close // state. The server must always close the connection after sending any of // this messages. #define MMP_SERVER_CLOSE_SHUTDOWN 0 // MMP_SERVER_CLOSE_SHUTDOWN // // Indicates that the server is closing the connection because it is // being shutdown. #define MMP_SERVER_CLOSE_SYSERROR 1 // MMP_SERVER_CLOSE_SYSERROR // // Indicates that the server is closing the connection because it came // across some error during a system call. A string describing the error // must be provided. #define MMP_SERVER_CLOSE_MMPERROR 2 // MMP_SERVER_CLOSE_MMPERROR // // Indicates that the reason for the server to be closing the connection // is that it violated the rules set forth in this documentation and // attempted to do something ilegal. A string describing the error must // be provided. #define MMP_SERVER_CLOSE_CLIENT 3 // MMP_SERVER_CLOSE_CLIENT // // Indicates that the server is closing the connection because it was // asked by the client to do so. #define MMP_SERVER_FRAME_DONE 1 // MMP_SERVER_FRAME_DONE // // Sends the client to the default state. This message has no arguments. // This is used by the server to indicate that no more objects are // available in a given universe. #define MMP_SERVER_FRAME_BULLET 2 // MMP_SERVER_FRAME_BULLET // // This message is used to pass information about a given bullet. The // message has two numbers as its arguments, for the x and the y position // of the bullet. // MESSAGES SENT BY THE CLIENT // // Right after the connection is established, the client must send the // following message: #define MMP_CLIENT_INITIAL_ID 1 // MMP_CLIENT_INITIAL_ID // // This is almost always the first message sent once a connection is // established. // // The message carries two arguments, both strings. The first identifies // the client (for example, "Matanza Artificial Inteligence Client") and // the second provides its version (for example, "0.12"). // // After sending this message, the client must wait for a reply from the // server. This reply can be any of the MMP_SERVER_INITIAL_* messages or // MMP_SERVER_CLOSE. // // The clients must wait for a reply to this message before sending any // other messages. // The following messages can be sent by the client when the server is in the // Default state: #define MMP_CLIENT_DEFAULT_JOIN 1 // MMP_CLIENT_DEFAULT_JOIN // // This message is sent by the client to subscribe to a universe. The // only argument it takes is the universe's id. #define MMP_CLIENT_DEFAULT_SHIPADD 2 // MMP_CLIENT_DEFAULT_SHIPADD // // This message indicates that the client wants to add a ship to a // universe. The message has two arguments, the first being a number // identifying the universe and the second being the name of the player. #define MMP_CLIENT_DEFAULT_SHIPEVENT 1 // MMP_CLIENT_DEFAULT_SHIPEVENT // // This message is used by the client to inform the server of one event // for a ship. Examples of events are shoting bullets, turning, // acelerating and so one. // // The message takes the ship's id (number) as its argument and sets the // server of the ShipEvent state, on which further information about the // event is sent. // Last changes to this specification: // // The following is a list of changes to this specification. // // 01/Mar/2001: // // - Added message MMP_CLIENT_DEFAULT_SHIPEVENT. // // - Modified the description for MMP_SERVER_DEFAULT_FRAME_SHIPS again. It // should be okay now. // // - Added the messages allowed in the Frame state. // // - Added MMP_CLIENT_INITIAL_ID and modified the semantics of establishing // a connection. // // - Added a list of missing things. // // 28/Feb/2001: // // - Modified the arguments of the MMP_SERVER_DEFAULT_FRAME_SHIPS message. // // - Changed PROTOCOL to MMP everywhere. // matanza-0.13/getopt.h0000644000175000017500000001075707156225364014737 0ustar boradminboradmin/* Declarations for getopt. Copyright (C) 1989,90,91,92,93,94,96,97 Free Software Foundation, Inc. NOTE: The canonical source of this file is maintained with the GNU C Library. Bugs can be reported to bug-glibc@gnu.org. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _GETOPT_H #define _GETOPT_H 1 #ifdef __cplusplus extern "C" { #endif /* For communication from `getopt' to the caller. When `getopt' finds an option that takes an argument, the argument value is returned here. Also, when `ordering' is RETURN_IN_ORDER, each non-option ARGV-element is returned here. */ extern char *optarg; /* Index in ARGV of the next element to be scanned. This is used for communication to and from the caller and for communication between successive calls to `getopt'. On entry to `getopt', zero means this is the first call; initialize. When `getopt' returns -1, this is the index of the first of the non-option elements that the caller should itself scan. Otherwise, `optind' communicates from one call to the next how much of ARGV has been scanned so far. */ extern int optind; /* Callers store zero here to inhibit the error message `getopt' prints for unrecognized options. */ extern int opterr; /* Set to an option character which was unrecognized. */ extern int optopt; /* Describe the long-named options requested by the application. The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector of `struct option' terminated by an element containing a name which is zero. The field `has_arg' is: no_argument (or 0) if the option does not take an argument, required_argument (or 1) if the option requires an argument, optional_argument (or 2) if the option takes an optional argument. If the field `flag' is not NULL, it points to a variable that is set to the value given in the field `val' when the option is found, but left unchanged if the option is not found. To have a long-named option do something other than set an `int' to a compiled-in constant, such as set a value from `optarg', set the option's `flag' field to zero and its `val' field to a nonzero value (the equivalent single-letter option character, if there is one). For long options that have a zero `flag' field, `getopt' returns the contents of the `val' field. */ struct option { #if defined (__STDC__) && __STDC__ const char *name; #else char *name; #endif /* has_arg can't be an enum because some compilers complain about type mismatches in all the code that assumes it is an int. */ int has_arg; int *flag; int val; }; /* Names for the values of the `has_arg' field of `struct option'. */ #define no_argument 0 #define required_argument 1 #define optional_argument 2 #if defined (__STDC__) && __STDC__ #ifdef __GNU_LIBRARY__ /* Many other libraries have conflicting prototypes for getopt, with differences in the consts, in stdlib.h. To avoid compilation errors, only prototype getopt for the GNU C library. */ extern int getopt (int argc, char *const *argv, const char *shortopts); #else /* not __GNU_LIBRARY__ */ extern int getopt (); #endif /* __GNU_LIBRARY__ */ extern int getopt_long (int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *longind); extern int getopt_long_only (int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *longind); /* Internal only. Users should not call this directly. */ extern int _getopt_internal (int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *longind, int long_only); #else /* not __STDC__ */ extern int getopt (); extern int getopt_long (); extern int getopt_long_only (); extern int _getopt_internal (); #endif /* __STDC__ */ #ifdef __cplusplus } #endif #endif /* getopt.h */ matanza-0.13/config.h.in0000644000175000017500000000765507261015360015300 0ustar boradminboradmin/* config.h.in. Generated automatically from configure.in by autoheader. */ /* Define to empty if the keyword does not work. */ #undef const /* Define if you don't have vprintf but do have _doprnt. */ #undef HAVE_DOPRNT /* Define if you have the vprintf function. */ #undef HAVE_VPRINTF /* Define to `unsigned' if doesn't define. */ #undef size_t /* Define if you have the ANSI C header files. */ #undef STDC_HEADERS /* Define if you can safely include both and . */ #undef TIME_WITH_SYS_TIME /* Define if your declares struct tm. */ #undef TM_IN_SYS_TIME /* Define to `int' if <> doesn't define it. */ #undef socklen_t /* Define if you have the GetTickCount function. */ #undef HAVE_GETTICKCOUNT /* Define if you have the Sleep function. */ #undef HAVE_SLEEP /* Define if you have the WSASocket function. */ #undef HAVE_WSASOCKET /* Define if you have the WSAStartup function. */ #undef HAVE_WSASTARTUP /* Define if you have the closesocket function. */ #undef HAVE_CLOSESOCKET /* Define if you have the fcntl function. */ #undef HAVE_FCNTL /* Define if you have the fork function. */ #undef HAVE_FORK /* Define if you have the gettimeofday function. */ #undef HAVE_GETTIMEOFDAY /* Define if you have the hstrerror function. */ #undef HAVE_HSTRERROR /* Define if you have the inet_ntoa function. */ #undef HAVE_INET_NTOA /* Define if you have the inet_ntop function. */ #undef HAVE_INET_NTOP /* Define if you have the ioctlsocket function. */ #undef HAVE_IOCTLSOCKET /* Define if you have the setsid function. */ #undef HAVE_SETSID /* Define if you have the setsockopt function. */ #undef HAVE_SETSOCKOPT /* Define if you have the signal function. */ #undef HAVE_SIGNAL /* Define if you have the snooze_until function. */ #undef HAVE_SNOOZE_UNTIL /* Define if you have the socket function. */ #undef HAVE_SOCKET /* Define if you have the strerror function. */ #undef HAVE_STRERROR /* Define if you have the strspn function. */ #undef HAVE_STRSPN /* Define if you have the system_time function. */ #undef HAVE_SYSTEM_TIME /* Define if you have the umask function. */ #undef HAVE_UMASK /* Define if you have the usleep function. */ #undef HAVE_USLEEP /* Define if you have the header file. */ #undef HAVE_ERRORS_H /* Define if you have the header file. */ #undef HAVE_OS_H /* Define if you have the header file. */ #undef HAVE_ARPA_INET_H /* Define if you have the header file. */ #undef HAVE_ARPA_TELNET_H /* Define if you have the header file. */ #undef HAVE_DIRECT_H /* Define if you have the header file. */ #undef HAVE_FCNTL_H /* Define if you have the header file. */ #undef HAVE_LIMITS_H /* Define if you have the header file. */ #undef HAVE_NETDB_H /* Define if you have the header file. */ #undef HAVE_NETINET_IN_H /* Define if you have the header file. */ #undef HAVE_PNG_H /* Define if you have the header file. */ #undef HAVE_SYS_IOCTL_H /* Define if you have the header file. */ #undef HAVE_SYS_SOCKET_H /* Define if you have the header file. */ #undef HAVE_SYS_TIME_H /* Define if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define if you have the header file. */ #undef HAVE_UNISTD_H /* Define if you have the header file. */ #undef HAVE_WINDOWS_H /* Define if you have the header file. */ #undef HAVE_WINSOCK2_H /* Define if you have the efence library (-lefence). */ #undef HAVE_LIBEFENCE /* Define if you have the m library (-lm). */ #undef HAVE_LIBM /* Define if you have the nsl library (-lnsl). */ #undef HAVE_LIBNSL /* Define if you have the socket library (-lsocket). */ #undef HAVE_LIBSOCKET /* Name of package */ #undef PACKAGE /* Version number of package */ #undef VERSION /* libpng was found */ #undef HAVE_LIBPNG matanza-0.13/winconfig.h0000644000175000017500000001025007260200126015365 0ustar boradminboradmin/* config.h. Generated automatically by configure. */ /* config.h.in. Generated automatically from configure.in by autoheader. */ /* Define to empty if the keyword does not work. */ /* #undef const */ /* Define if you don't have vprintf but do have _doprnt. */ /* #undef HAVE_DOPRNT */ /* Define if you have the vprintf function. */ #define HAVE_VPRINTF 1 /* Define to `unsigned' if doesn't define. */ /* #undef size_t */ /* Define if you have the ANSI C header files. */ #define STDC_HEADERS 1 /* Define if you can safely include both and . */ /* #undef TIME_WITH_SYS_TIME */ /* Define if your declares struct tm. */ /* #undef TM_IN_SYS_TIME */ /* Define to `int' if <> doesn't define it. */ #define socklen_t int /* Define if you have the GetTickCount function. */ #define HAVE_GETTICKCOUNT 1 /* Define if you have the Sleep function. */ #define HAVE_SLEEP 1 /* Define if you have the WSASocket function. */ #define HAVE_WSASOCKET 1 /* Define if you have the WSAStartup function. */ #define HAVE_WSASTARTUP 1 /* Define if you have the closesocket function. */ #define HAVE_CLOSESOCKET 1 /* Define if you have the fcntl function. */ /* #undef HAVE_FCNTL */ /* Define if you have the fork function. */ /* #undef HAVE_FORK */ /* Define if you have the gettimeofday function. */ /* #undef HAVE_GETTIMEOFDAY */ /* Define if you have the hstrerror function. */ /* #undef HAVE_HSTRERROR */ /* Define if you have the inet_ntoa function. */ #define HAVE_INET_NTOA 1 /* Define if you have the inet_ntop function. */ /* #undef HAVE_INET_NTOP */ /* Define if you have the ioctlsocket function. */ #define HAVE_IOCTLSOCKET 1 /* Define if you have the setsid function. */ /* #undef HAVE_SETSID */ /* Define if you have the setsockopt function. */ #define HAVE_SETSOCKOPT 1 /* Define if you have the signal function. */ #define HAVE_SIGNAL 1 /* Define if you have the snooze_until function. */ /* #undef HAVE_SNOOZE_UNTIL */ /* Define if you have the socket function. */ /* #undef HAVE_SOCKET */ /* Define if you have the strerror function. */ #define HAVE_STRERROR 1 /* Define if you have the strspn function. */ /* #undef HAVE_STRSPN */ /* Define if you have the system_time function. */ /* #undef HAVE_SYSTEM_TIME */ /* Define if you have the usleep function. */ /* #undef HAVE_USLEEP */ /* Define if you have the header file. */ /* #undef HAVE_ARPA_INET_H */ /* Define if you have the header file. */ /* #undef HAVE_ARPA_TELNET_H */ /* Define if you have the header file. */ /* #undef HAVE_OS_H */ /* Define if you have the header file. */ /* #undef HAVE_ERRORS_H */ /* Define if you have the header file. */ /* #undef HAVE_FCNTL_H */ /* Define if you have the header file. */ /* #undef HAVE_LIMITS_H */ /* Define if you have the header file. */ /* #undef HAVE_NETDB_H */ /* Define if you have the header file. */ /* #undef HAVE_NETINET_IN_H */ /* Define if you have the header file. */ /* #undef HAVE_PNG_H */ /* Define if you have the header file. */ /* #undef HAVE_SYS_IOCTL_H */ /* Define if you have the header file. */ /* #undef HAVE_SYS_SOCKET_H */ /* Define if you have the header file. */ /* #undef HAVE_SYS_TIME_H */ /* Define if you have the header file. */ /* #undef HAVE_SYS_TYPES_H */ /* Define if you have the header file. */ /* #undef HAVE_UNISTD_H */ /* Define if you have the header file. */ #define HAVE_WINDOWS_H 1 /* Define if you have the header file. */ #define HAVE_WINSOCK2_H 1 /* Define if you have the efence library (-lefence). */ /* #undef HAVE_LIBEFENCE */ /* Define if you have the m library (-lm). */ /* #undef HAVE_LIBM */ /* Define if you have the nsl library (-lnsl). */ /* #undef HAVE_LIBNSL */ /* Define if you have the socket library (-lsocket). */ /* #undef HAVE_LIBSOCKET */ /* Name of package */ #define PACKAGE "matanza" /* Version number of package */ #define VERSION "0.13-pre0" /* libpng was found */ /* #undef HAVE_LIBPNG */ /* Gnome's libxml was found */ /* #undef HAVE_LIBXML */ matanza-0.13/getopt.c0000644000175000017500000007264307156225364014734 0ustar boradminboradmin/* Getopt for GNU. NOTE: getopt is now part of the C library, so if you don't know what "Keep this file name-space clean" means, talk to drepper@gnu.org before changing it! Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98 Free Software Foundation, Inc. NOTE: The canonical source of this file is maintained with the GNU C Library. Bugs can be reported to bug-glibc@gnu.org. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* This tells Alpha OSF/1 not to define a getopt prototype in . Ditto for AIX 3.2 and . */ #ifndef _NO_PROTO # define _NO_PROTO #endif #ifdef HAVE_CONFIG_H # include #endif #if !defined __STDC__ || !__STDC__ /* This is a separate conditional since some stdc systems reject `defined (const)'. */ # ifndef const # define const # endif #endif #include /* Comment out all this code if we are using the GNU C Library, and are not actually compiling the library itself. This code is part of the GNU C Library, but also included in many other GNU distributions. Compiling and linking in this code is a waste when using the GNU C library (especially if it is a shared library). Rather than having every GNU program understand `configure --with-gnu-libc' and omit the object files, it is simpler to just do this in the source for each such file. */ #define GETOPT_INTERFACE_VERSION 2 #if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2 # include # if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION # define ELIDE_CODE # endif #endif #ifndef ELIDE_CODE /* This needs to come after some library #include to get __GNU_LIBRARY__ defined. */ #ifdef __GNU_LIBRARY__ /* Don't include stdlib.h for non-GNU C libraries because some of them contain conflicting prototypes for getopt. */ # include # include #endif /* GNU C library. */ #ifdef VMS # include # if HAVE_STRING_H - 0 # include # endif #endif #ifndef _ /* This is for other GNU distributions with internationalized messages. When compiling libc, the _ macro is predefined. */ # ifdef HAVE_LIBINTL_H # include # define _(msgid) gettext (msgid) # else # define _(msgid) (msgid) # endif #endif /* This version of `getopt' appears to the caller like standard Unix `getopt' but it behaves differently for the user, since it allows the user to intersperse the options with the other arguments. As `getopt' works, it permutes the elements of ARGV so that, when it is done, all the options precede everything else. Thus all application programs are extended to handle flexible argument order. Setting the environment variable POSIXLY_CORRECT disables permutation. Then the behavior is completely standard. GNU application programs can use a third alternative mode in which they can distinguish the relative order of options and other arguments. */ #include "getopt.h" /* For communication from `getopt' to the caller. When `getopt' finds an option that takes an argument, the argument value is returned here. Also, when `ordering' is RETURN_IN_ORDER, each non-option ARGV-element is returned here. */ char *optarg = NULL; /* Index in ARGV of the next element to be scanned. This is used for communication to and from the caller and for communication between successive calls to `getopt'. On entry to `getopt', zero means this is the first call; initialize. When `getopt' returns -1, this is the index of the first of the non-option elements that the caller should itself scan. Otherwise, `optind' communicates from one call to the next how much of ARGV has been scanned so far. */ /* 1003.2 says this must be 1 before any call. */ int optind = 1; /* Formerly, initialization of getopt depended on optind==0, which causes problems with re-calling getopt as programs generally don't know that. */ int __getopt_initialized = 0; /* The next char to be scanned in the option-element in which the last option character we returned was found. This allows us to pick up the scan where we left off. If this is zero, or a null string, it means resume the scan by advancing to the next ARGV-element. */ static char *nextchar; /* Callers store zero here to inhibit the error message for unrecognized options. */ int opterr = 1; /* Set to an option character which was unrecognized. This must be initialized on some systems to avoid linking in the system's own getopt implementation. */ int optopt = '?'; /* Describe how to deal with options that follow non-option ARGV-elements. If the caller did not specify anything, the default is REQUIRE_ORDER if the environment variable POSIXLY_CORRECT is defined, PERMUTE otherwise. REQUIRE_ORDER means don't recognize them as options; stop option processing when the first non-option is seen. This is what Unix does. This mode of operation is selected by either setting the environment variable POSIXLY_CORRECT, or using `+' as the first character of the list of option characters. PERMUTE is the default. We permute the contents of ARGV as we scan, so that eventually all the non-options are at the end. This allows options to be given in any order, even with programs that were not written to expect this. RETURN_IN_ORDER is an option available to programs that were written to expect options and other ARGV-elements in any order and that care about the ordering of the two. We describe each non-option ARGV-element as if it were the argument of an option with character code 1. Using `-' as the first character of the list of option characters selects this mode of operation. The special argument `--' forces an end of option-scanning regardless of the value of `ordering'. In the case of RETURN_IN_ORDER, only `--' can cause `getopt' to return -1 with `optind' != ARGC. */ static enum { REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER } ordering; /* Value of POSIXLY_CORRECT environment variable. */ static char *posixly_correct; #ifdef __GNU_LIBRARY__ /* We want to avoid inclusion of string.h with non-GNU libraries because there are many ways it can cause trouble. On some systems, it contains special magic macros that don't work in GCC. */ # include # define my_index strchr #else # if HAVE_STRING_H # include # else # include # endif /* Avoid depending on library functions or files whose names are inconsistent. */ #ifndef getenv extern char *getenv (); #endif static char * my_index (str, chr) const char *str; int chr; { while (*str) { if (*str == chr) return (char *) str; str++; } return 0; } /* If using GCC, we can safely declare strlen this way. If not using GCC, it is ok not to declare it. */ #ifdef __GNUC__ /* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. That was relevant to code that was here before. */ # if (!defined __STDC__ || !__STDC__) && !defined strlen /* gcc with -traditional declares the built-in strlen to return int, and has done so at least since version 2.4.5. -- rms. */ extern int strlen (const char *); # endif /* not __STDC__ */ #endif /* __GNUC__ */ #endif /* not __GNU_LIBRARY__ */ /* Handle permutation of arguments. */ /* Describe the part of ARGV that contains non-options that have been skipped. `first_nonopt' is the index in ARGV of the first of them; `last_nonopt' is the index after the last of them. */ static int first_nonopt; static int last_nonopt; #ifdef _LIBC /* Bash 2.0 gives us an environment variable containing flags indicating ARGV elements that should not be considered arguments. */ /* Defined in getopt_init.c */ extern char *__getopt_nonoption_flags; static int nonoption_flags_max_len; static int nonoption_flags_len; static int original_argc; static char *const *original_argv; /* Make sure the environment variable bash 2.0 puts in the environment is valid for the getopt call we must make sure that the ARGV passed to getopt is that one passed to the process. */ static void __attribute__ ((unused)) store_args_and_env (int argc, char *const *argv) { /* XXX This is no good solution. We should rather copy the args so that we can compare them later. But we must not use malloc(3). */ original_argc = argc; original_argv = argv; } # ifdef text_set_element text_set_element (__libc_subinit, store_args_and_env); # endif /* text_set_element */ # define SWAP_FLAGS(ch1, ch2) \ if (nonoption_flags_len > 0) \ { \ char __tmp = __getopt_nonoption_flags[ch1]; \ __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \ __getopt_nonoption_flags[ch2] = __tmp; \ } #else /* !_LIBC */ # define SWAP_FLAGS(ch1, ch2) #endif /* _LIBC */ /* Exchange two adjacent subsequences of ARGV. One subsequence is elements [first_nonopt,last_nonopt) which contains all the non-options that have been skipped so far. The other is elements [last_nonopt,optind), which contains all the options processed since those non-options were skipped. `first_nonopt' and `last_nonopt' are relocated so that they describe the new indices of the non-options in ARGV after they are moved. */ #if defined __STDC__ && __STDC__ static void exchange (char **); #endif static void exchange (argv) char **argv; { int bottom = first_nonopt; int middle = last_nonopt; int top = optind; char *tem; /* Exchange the shorter segment with the far end of the longer segment. That puts the shorter segment into the right place. It leaves the longer segment in the right place overall, but it consists of two parts that need to be swapped next. */ #ifdef _LIBC /* First make sure the handling of the `__getopt_nonoption_flags' string can work normally. Our top argument must be in the range of the string. */ if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len) { /* We must extend the array. The user plays games with us and presents new arguments. */ char *new_str = malloc (top + 1); if (new_str == NULL) nonoption_flags_len = nonoption_flags_max_len = 0; else { memset (__mempcpy (new_str, __getopt_nonoption_flags, nonoption_flags_max_len), '\0', top + 1 - nonoption_flags_max_len); nonoption_flags_max_len = top + 1; __getopt_nonoption_flags = new_str; } } #endif while (top > middle && middle > bottom) { if (top - middle > middle - bottom) { /* Bottom segment is the short one. */ int len = middle - bottom; register int i; /* Swap it with the top part of the top segment. */ for (i = 0; i < len; i++) { tem = argv[bottom + i]; argv[bottom + i] = argv[top - (middle - bottom) + i]; argv[top - (middle - bottom) + i] = tem; SWAP_FLAGS (bottom + i, top - (middle - bottom) + i); } /* Exclude the moved bottom segment from further swapping. */ top -= len; } else { /* Top segment is the short one. */ int len = top - middle; register int i; /* Swap it with the bottom part of the bottom segment. */ for (i = 0; i < len; i++) { tem = argv[bottom + i]; argv[bottom + i] = argv[middle + i]; argv[middle + i] = tem; SWAP_FLAGS (bottom + i, middle + i); } /* Exclude the moved top segment from further swapping. */ bottom += len; } } /* Update records for the slots the non-options now occupy. */ first_nonopt += (optind - last_nonopt); last_nonopt = optind; } /* Initialize the internal data when the first call is made. */ #if defined __STDC__ && __STDC__ static const char *_getopt_initialize (int, char *const *, const char *); #endif static const char * _getopt_initialize (argc, argv, optstring) int argc; char *const *argv; const char *optstring; { /* Start processing options with ARGV-element 1 (since ARGV-element 0 is the program name); the sequence of previously skipped non-option ARGV-elements is empty. */ first_nonopt = last_nonopt = optind; nextchar = NULL; posixly_correct = getenv ("POSIXLY_CORRECT"); /* Determine how to handle the ordering of options and nonoptions. */ if (optstring[0] == '-') { ordering = RETURN_IN_ORDER; ++optstring; } else if (optstring[0] == '+') { ordering = REQUIRE_ORDER; ++optstring; } else if (posixly_correct != NULL) ordering = REQUIRE_ORDER; else ordering = PERMUTE; #ifdef _LIBC if (posixly_correct == NULL && argc == original_argc && argv == original_argv) { if (nonoption_flags_max_len == 0) { if (__getopt_nonoption_flags == NULL || __getopt_nonoption_flags[0] == '\0') nonoption_flags_max_len = -1; else { const char *orig_str = __getopt_nonoption_flags; int len = nonoption_flags_max_len = strlen (orig_str); if (nonoption_flags_max_len < argc) nonoption_flags_max_len = argc; __getopt_nonoption_flags = (char *) malloc (nonoption_flags_max_len); if (__getopt_nonoption_flags == NULL) nonoption_flags_max_len = -1; else memset (__mempcpy (__getopt_nonoption_flags, orig_str, len), '\0', nonoption_flags_max_len - len); } } nonoption_flags_len = nonoption_flags_max_len; } else nonoption_flags_len = 0; #endif return optstring; } /* Scan elements of ARGV (whose length is ARGC) for option characters given in OPTSTRING. If an element of ARGV starts with '-', and is not exactly "-" or "--", then it is an option element. The characters of this element (aside from the initial '-') are option characters. If `getopt' is called repeatedly, it returns successively each of the option characters from each of the option elements. If `getopt' finds another option character, it returns that character, updating `optind' and `nextchar' so that the next call to `getopt' can resume the scan with the following option character or ARGV-element. If there are no more option characters, `getopt' returns -1. Then `optind' is the index in ARGV of the first ARGV-element that is not an option. (The ARGV-elements have been permuted so that those that are not options now come last.) OPTSTRING is a string containing the legitimate option characters. If an option character is seen that is not listed in OPTSTRING, return '?' after printing an error message. If you set `opterr' to zero, the error message is suppressed but we still return '?'. If a char in OPTSTRING is followed by a colon, that means it wants an arg, so the following text in the same ARGV-element, or the text of the following ARGV-element, is returned in `optarg'. Two colons mean an option that wants an optional arg; if there is text in the current ARGV-element, it is returned in `optarg', otherwise `optarg' is set to zero. If OPTSTRING starts with `-' or `+', it requests different methods of handling the non-option ARGV-elements. See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. Long-named options begin with `--' instead of `-'. Their names may be abbreviated as long as the abbreviation is unique or is an exact match for some defined option. If they have an argument, it follows the option name in the same ARGV-element, separated from the option name by a `=', or else the in next ARGV-element. When `getopt' finds a long-named option, it returns 0 if that option's `flag' field is nonzero, the value of the option's `val' field if the `flag' field is zero. The elements of ARGV aren't really const, because we permute them. But we pretend they're const in the prototype to be compatible with other systems. LONGOPTS is a vector of `struct option' terminated by an element containing a name which is zero. LONGIND returns the index in LONGOPT of the long-named option found. It is only valid when a long-named option has been found by the most recent call. If LONG_ONLY is nonzero, '-' as well as '--' can introduce long-named options. */ int _getopt_internal (argc, argv, optstring, longopts, longind, long_only) int argc; char *const *argv; const char *optstring; const struct option *longopts; int *longind; int long_only; { optarg = NULL; if (optind == 0 || !__getopt_initialized) { if (optind == 0) optind = 1; /* Don't scan ARGV[0], the program name. */ optstring = _getopt_initialize (argc, argv, optstring); __getopt_initialized = 1; } /* Test whether ARGV[optind] points to a non-option argument. Either it does not have option syntax, or there is an environment flag from the shell indicating it is not an option. The later information is only used when the used in the GNU libc. */ #ifdef _LIBC # define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \ || (optind < nonoption_flags_len \ && __getopt_nonoption_flags[optind] == '1')) #else # define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0') #endif if (nextchar == NULL || *nextchar == '\0') { /* Advance to the next ARGV-element. */ /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been moved back by the user (who may also have changed the arguments). */ if (last_nonopt > optind) last_nonopt = optind; if (first_nonopt > optind) first_nonopt = optind; if (ordering == PERMUTE) { /* If we have just processed some options following some non-options, exchange them so that the options come first. */ if (first_nonopt != last_nonopt && last_nonopt != optind) exchange ((char **) argv); else if (last_nonopt != optind) first_nonopt = optind; /* Skip any additional non-options and extend the range of non-options previously skipped. */ while (optind < argc && NONOPTION_P) optind++; last_nonopt = optind; } /* The special ARGV-element `--' means premature end of options. Skip it like a null option, then exchange with previous non-options as if it were an option, then skip everything else like a non-option. */ if (optind != argc && !strcmp (argv[optind], "--")) { optind++; if (first_nonopt != last_nonopt && last_nonopt != optind) exchange ((char **) argv); else if (first_nonopt == last_nonopt) first_nonopt = optind; last_nonopt = argc; optind = argc; } /* If we have done all the ARGV-elements, stop the scan and back over any non-options that we skipped and permuted. */ if (optind == argc) { /* Set the next-arg-index to point at the non-options that we previously skipped, so the caller will digest them. */ if (first_nonopt != last_nonopt) optind = first_nonopt; return -1; } /* If we have come to a non-option and did not permute it, either stop the scan or describe it to the caller and pass it by. */ if (NONOPTION_P) { if (ordering == REQUIRE_ORDER) return -1; optarg = argv[optind++]; return 1; } /* We have found another option-ARGV-element. Skip the initial punctuation. */ nextchar = (argv[optind] + 1 + (longopts != NULL && argv[optind][1] == '-')); } /* Decode the current option-ARGV-element. */ /* Check whether the ARGV-element is a long option. If long_only and the ARGV-element has the form "-f", where f is a valid short option, don't consider it an abbreviated form of a long option that starts with f. Otherwise there would be no way to give the -f short option. On the other hand, if there's a long option "fubar" and the ARGV-element is "-fu", do consider that an abbreviation of the long option, just like "--fu", and not "-f" with arg "u". This distinction seems to be the most useful approach. */ if (longopts != NULL && (argv[optind][1] == '-' || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1]))))) { char *nameend; const struct option *p; const struct option *pfound = NULL; int exact = 0; int ambig = 0; int indfound = -1; int option_index; for (nameend = nextchar; *nameend && *nameend != '='; nameend++) /* Do nothing. */ ; /* Test all long options for either exact match or abbreviated matches. */ for (p = longopts, option_index = 0; p->name; p++, option_index++) if (!strncmp (p->name, nextchar, nameend - nextchar)) { if ((unsigned int) (nameend - nextchar) == (unsigned int) strlen (p->name)) { /* Exact match found. */ pfound = p; indfound = option_index; exact = 1; break; } else if (pfound == NULL) { /* First nonexact match found. */ pfound = p; indfound = option_index; } else /* Second or later nonexact match found. */ ambig = 1; } if (ambig && !exact) { if (opterr) fprintf (stderr, _("%s: option `%s' is ambiguous\n"), argv[0], argv[optind]); nextchar += strlen (nextchar); optind++; optopt = 0; return '?'; } if (pfound != NULL) { option_index = indfound; optind++; if (*nameend) { /* Don't test has_arg with >, because some C compilers don't allow it to be used on enums. */ if (pfound->has_arg) optarg = nameend + 1; else { if (opterr) if (argv[optind - 1][1] == '-') /* --option */ fprintf (stderr, _("%s: option `--%s' doesn't allow an argument\n"), argv[0], pfound->name); else /* +option or -option */ fprintf (stderr, _("%s: option `%c%s' doesn't allow an argument\n"), argv[0], argv[optind - 1][0], pfound->name); nextchar += strlen (nextchar); optopt = pfound->val; return '?'; } } else if (pfound->has_arg == 1) { if (optind < argc) optarg = argv[optind++]; else { if (opterr) fprintf (stderr, _("%s: option `%s' requires an argument\n"), argv[0], argv[optind - 1]); nextchar += strlen (nextchar); optopt = pfound->val; return optstring[0] == ':' ? ':' : '?'; } } nextchar += strlen (nextchar); if (longind != NULL) *longind = option_index; if (pfound->flag) { *(pfound->flag) = pfound->val; return 0; } return pfound->val; } /* Can't find it as a long option. If this is not getopt_long_only, or the option starts with '--' or is not a valid short option, then it's an error. Otherwise interpret it as a short option. */ if (!long_only || argv[optind][1] == '-' || my_index (optstring, *nextchar) == NULL) { if (opterr) { if (argv[optind][1] == '-') /* --option */ fprintf (stderr, _("%s: unrecognized option `--%s'\n"), argv[0], nextchar); else /* +option or -option */ fprintf (stderr, _("%s: unrecognized option `%c%s'\n"), argv[0], argv[optind][0], nextchar); } nextchar = (char *) ""; optind++; optopt = 0; return '?'; } } /* Look at and handle the next short option-character. */ { char c = *nextchar++; char *temp = my_index (optstring, c); /* Increment `optind' when we start to process its last character. */ if (*nextchar == '\0') ++optind; if (temp == NULL || c == ':') { if (opterr) { if (posixly_correct) /* 1003.2 specifies the format of this message. */ fprintf (stderr, _("%s: illegal option -- %c\n"), argv[0], c); else fprintf (stderr, _("%s: invalid option -- %c\n"), argv[0], c); } optopt = c; return '?'; } /* Convenience. Treat POSIX -W foo same as long option --foo */ if (temp[0] == 'W' && temp[1] == ';') { char *nameend; const struct option *p; const struct option *pfound = NULL; int exact = 0; int ambig = 0; int indfound = 0; int option_index; /* This is an option that requires an argument. */ if (*nextchar != '\0') { optarg = nextchar; /* If we end this ARGV-element by taking the rest as an arg, we must advance to the next element now. */ optind++; } else if (optind == argc) { if (opterr) { /* 1003.2 specifies the format of this message. */ fprintf (stderr, _("%s: option requires an argument -- %c\n"), argv[0], c); } optopt = c; if (optstring[0] == ':') c = ':'; else c = '?'; return c; } else /* We already incremented `optind' once; increment it again when taking next ARGV-elt as argument. */ optarg = argv[optind++]; /* optarg is now the argument, see if it's in the table of longopts. */ for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++) /* Do nothing. */ ; /* Test all long options for either exact match or abbreviated matches. */ for (p = longopts, option_index = 0; p->name; p++, option_index++) if (!strncmp (p->name, nextchar, nameend - nextchar)) { if ((unsigned int) (nameend - nextchar) == strlen (p->name)) { /* Exact match found. */ pfound = p; indfound = option_index; exact = 1; break; } else if (pfound == NULL) { /* First nonexact match found. */ pfound = p; indfound = option_index; } else /* Second or later nonexact match found. */ ambig = 1; } if (ambig && !exact) { if (opterr) fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"), argv[0], argv[optind]); nextchar += strlen (nextchar); optind++; return '?'; } if (pfound != NULL) { option_index = indfound; if (*nameend) { /* Don't test has_arg with >, because some C compilers don't allow it to be used on enums. */ if (pfound->has_arg) optarg = nameend + 1; else { if (opterr) fprintf (stderr, _("\ %s: option `-W %s' doesn't allow an argument\n"), argv[0], pfound->name); nextchar += strlen (nextchar); return '?'; } } else if (pfound->has_arg == 1) { if (optind < argc) optarg = argv[optind++]; else { if (opterr) fprintf (stderr, _("%s: option `%s' requires an argument\n"), argv[0], argv[optind - 1]); nextchar += strlen (nextchar); return optstring[0] == ':' ? ':' : '?'; } } nextchar += strlen (nextchar); if (longind != NULL) *longind = option_index; if (pfound->flag) { *(pfound->flag) = pfound->val; return 0; } return pfound->val; } nextchar = NULL; return 'W'; /* Let the application handle it. */ } if (temp[1] == ':') { if (temp[2] == ':') { /* This is an option that accepts an argument optionally. */ if (*nextchar != '\0') { optarg = nextchar; optind++; } else optarg = NULL; nextchar = NULL; } else { /* This is an option that requires an argument. */ if (*nextchar != '\0') { optarg = nextchar; /* If we end this ARGV-element by taking the rest as an arg, we must advance to the next element now. */ optind++; } else if (optind == argc) { if (opterr) { /* 1003.2 specifies the format of this message. */ fprintf (stderr, _("%s: option requires an argument -- %c\n"), argv[0], c); } optopt = c; if (optstring[0] == ':') c = ':'; else c = '?'; } else /* We already incremented `optind' once; increment it again when taking next ARGV-elt as argument. */ optarg = argv[optind++]; nextchar = NULL; } } return c; } } int getopt (argc, argv, optstring) int argc; char *const *argv; const char *optstring; { return _getopt_internal (argc, argv, optstring, (const struct option *) 0, (int *) 0, 0); } #endif /* Not ELIDE_CODE. */ #ifdef TEST /* Compile with -DTEST to make an executable for use in testing the above definition of `getopt'. */ int main (argc, argv) int argc; char **argv; { int c; int digit_optind = 0; while (1) { int this_option_optind = optind ? optind : 1; c = getopt (argc, argv, "abc:d:0123456789"); if (c == -1) break; switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (digit_optind != 0 && digit_optind != this_option_optind) printf ("digits occur in two different argv-elements.\n"); digit_optind = this_option_optind; printf ("option %c\n", c); break; case 'a': printf ("option a\n"); break; case 'b': printf ("option b\n"); break; case 'c': printf ("option c with value `%s'\n", optarg); break; case '?': break; default: printf ("?? getopt returned character code 0%o ??\n", c); } } if (optind < argc) { printf ("non-option ARGV-elements: "); while (optind < argc) printf ("%s ", argv[optind++]); printf ("\n"); } exit (0); } #endif /* TEST */ matanza-0.13/aclocal.m40000644000175000017500000001134407263463402015111 0ustar boradminboradmindnl aclocal.m4 generated automatically by aclocal 1.4 dnl Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl This program is distributed in the hope that it will be useful, dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A dnl PARTICULAR PURPOSE. # Do all the work for Automake. This macro actually does too much -- # some checks are only needed if your package does certain things. # But this isn't really a big deal. # serial 1 dnl Usage: dnl AM_INIT_AUTOMAKE(package,version, [no-define]) AC_DEFUN(AM_INIT_AUTOMAKE, [AC_REQUIRE([AC_PROG_INSTALL]) PACKAGE=[$1] AC_SUBST(PACKAGE) VERSION=[$2] AC_SUBST(VERSION) dnl test to see if srcdir already configured if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) fi ifelse([$3],, AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])) AC_REQUIRE([AM_SANITY_CHECK]) AC_REQUIRE([AC_ARG_PROGRAM]) dnl FIXME This is truly gross. missing_dir=`cd $ac_aux_dir && pwd` AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir) AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir) AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir) AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir) AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir) AC_REQUIRE([AC_PROG_MAKE_SET])]) # # Check to make sure that the build environment is sane. # AC_DEFUN(AM_SANITY_CHECK, [AC_MSG_CHECKING([whether build environment is sane]) # Just in case sleep 1 echo timestamp > conftestfile # Do `set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null` if test "[$]*" = "X"; then # -L didn't work. set X `ls -t $srcdir/configure conftestfile` fi if test "[$]*" != "X $srcdir/configure conftestfile" \ && test "[$]*" != "X conftestfile $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken alias in your environment]) fi test "[$]2" = conftestfile ) then # Ok. : else AC_MSG_ERROR([newly created file is older than distributed files! Check your system clock]) fi rm -f conftest* AC_MSG_RESULT(yes)]) dnl AM_MISSING_PROG(NAME, PROGRAM, DIRECTORY) dnl The program must properly implement --version. AC_DEFUN(AM_MISSING_PROG, [AC_MSG_CHECKING(for working $2) # Run test in a subshell; some versions of sh will print an error if # an executable is not found, even if stderr is redirected. # Redirect stdin to placate older versions of autoconf. Sigh. if ($2 --version) < /dev/null > /dev/null 2>&1; then $1=$2 AC_MSG_RESULT(found) else $1="$3/missing $2" AC_MSG_RESULT(missing) fi AC_SUBST($1)]) # Like AC_CONFIG_HEADER, but automatically create stamp file. AC_DEFUN(AM_CONFIG_HEADER, [AC_PREREQ([2.12]) AC_CONFIG_HEADER([$1]) dnl When config.status generates a header, we must update the stamp-h file. dnl This file resides in the same directory as the config header dnl that is generated. We must strip everything past the first ":", dnl and everything past the last "/". AC_OUTPUT_COMMANDS(changequote(<<,>>)dnl ifelse(patsubst(<<$1>>, <<[^ ]>>, <<>>), <<>>, <>CONFIG_HEADERS" || echo timestamp > patsubst(<<$1>>, <<^\([^:]*/\)?.*>>, <<\1>>)stamp-h<<>>dnl>>, <>; do case " <<$>>CONFIG_HEADERS " in *" <<$>>am_file "*<<)>> echo timestamp > `echo <<$>>am_file | sed -e 's%:.*%%' -e 's%[^/]*$%%'`stamp-h$am_indx ;; esac am_indx=`expr "<<$>>am_indx" + 1` done<<>>dnl>>) changequote([,]))]) AC_DEFUN(TYPE_SOCKLEN_T, [AC_CACHE_CHECK([for socklen_t], ac_cv_type_socklen_t, [ AC_TRY_COMPILE( [#include #include ], [socklen_t len = 42; return 0;], ac_cv_type_socklen_t=yes, ac_cv_type_socklen_t=no) ]) if test $ac_cv_type_socklen_t != yes; then AC_DEFINE(socklen_t, int) fi ]) matanza-0.13/configure.in0000644000175000017500000000552207263463375015574 0ustar boradminboradmindnl Process this file with autoconf to produce a configure script. AC_INIT(matanza.w) dnl For the moment, if you change the version, don't forget to change it on dnl winconfig.h. AM_INIT_AUTOMAKE(matanza, 0.13) AC_PREREQ(2.12) AM_CONFIG_HEADER(config.h) dnl Checks for programs. AC_PROG_CC AC_PROG_INSTALL AC_PROG_LN_S AC_PROG_MAKE_SET dnl We should also check for cweave/ctangle. dnl ===================================================================== dnl These are nice to have. They don't hurt. CFLAGS="-DMATANZA_ASSERT=1 -DMATANZA_VERBOSE=1" AC_ARG_ENABLE(profile, [ --enable-profile turn on profiling [default=no]], if test "x$enable_profile" = xyes; then CFLAGS="-pg $CFLAGS" fi) AC_ARG_ENABLE(debug, [ --enable-debug turn on debugging [default=no]], if test "x$enable_debug" = xyes; then CFLAGS="-g $CFLAGS" fi) AC_ARG_ENABLE(efence, [ --enable-efence Link against efence [default=no]], if test "x$enable_efence" = xyes; then AC_CHECK_LIB(efence, malloc) fi) dnl ===================================================================== AC_CHECK_HEADERS(png.h) AC_CHECK_LIB(png, png_sig_cmp, [ LIBS="$LIBS -lpng" HAVE_LIBPNG="1" AC_DEFINE_UNQUOTED(HAVE_LIBPNG, 1, libpng was found) ], [HAVE_LIBPNG="0"]) dnl ===================================================================== dnl We use libm for trigonometric functions. AC_CHECK_LIB(m, sin) dnl ===================================================================== CFLAGS="$CFLAGS -DXML_MIN_SIZE" dnl ===================================================================== dnl In Solaris/SunOS you need -lsocket if you use socket() and -lnsl dnl if you use inet_addr AC_CHECK_LIB(socket, socket) AC_CHECK_LIB(nsl, inet_ntoa) dnl ===================================================================== dnl Checks for header files. AC_HEADER_STDC dnl Headers for Unix: AC_CHECK_HEADERS(fcntl.h limits.h unistd.h arpa/telnet.h netdb.h netinet/in.h arpa/inet.h sys/ioctl.h sys/time.h sys/types.h sys/socket.h) dnl Headers for Windows: AC_CHECK_HEADERS(winsock2.h windows.h direct.h) dnl Headers for BeOS: AC_CHECK_HEADERS(OS.h Errors.h) dnl ===================================================================== dnl Checks for typedefs, structures, and compiler characteristics. AC_C_CONST AC_TYPE_SIZE_T AC_HEADER_TIME AC_STRUCT_TM TYPE_SOCKLEN_T dnl ===================================================================== dnl Checks for library functions. AC_FUNC_MEMCMP AC_FUNC_VPRINTF AC_CHECK_FUNCS(signal fork setsid socket fcntl strerror strspn inet_ntop inet_ntoa ioctlsocket hstrerror usleep Sleep gettimeofday snooze_until system_time GetTickCount setsockopt WSASocket WSAStartup closesocket umask) dnl ===================================================================== AC_OUTPUT(Makefile) dnl ===================================================================== matanza-0.13/install-sh0000744000175000017500000001273607107673453015267 0ustar boradminboradmin#!/bin/sh # # install - install a program, script, or datafile # This comes from X11R5 (mit/util/scripts/install.sh). # # Copyright 1991 by the Massachusetts Institute of Technology # # Permission to use, copy, modify, distribute, and sell this software and its # documentation for any purpose is hereby granted without fee, provided that # the above copyright notice appear in all copies and that both that # copyright notice and this permission notice appear in supporting # documentation, and that the name of M.I.T. not be used in advertising or # publicity pertaining to distribution of the software without specific, # written prior permission. M.I.T. makes no representations about the # suitability of this software for any purpose. It is provided "as is" # without express or implied warranty. # # Calling this script install-sh is preferred over install.sh, to prevent # `make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. It can only install one file at a time, a restriction # shared with many OS's install programs. # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit="${DOITPROG-}" # put in absolute paths if you don't have them in your path; or use env. vars. mvprog="${MVPROG-mv}" cpprog="${CPPROG-cp}" chmodprog="${CHMODPROG-chmod}" chownprog="${CHOWNPROG-chown}" chgrpprog="${CHGRPPROG-chgrp}" stripprog="${STRIPPROG-strip}" rmprog="${RMPROG-rm}" mkdirprog="${MKDIRPROG-mkdir}" transformbasename="" transform_arg="" instcmd="$mvprog" chmodcmd="$chmodprog 0755" chowncmd="" chgrpcmd="" stripcmd="" rmcmd="$rmprog -f" mvcmd="$mvprog" src="" dst="" dir_arg="" while [ x"$1" != x ]; do case $1 in -c) instcmd="$cpprog" shift continue;; -d) dir_arg=true shift continue;; -m) chmodcmd="$chmodprog $2" shift shift continue;; -o) chowncmd="$chownprog $2" shift shift continue;; -g) chgrpcmd="$chgrpprog $2" shift shift continue;; -s) stripcmd="$stripprog" shift continue;; -t=*) transformarg=`echo $1 | sed 's/-t=//'` shift continue;; -b=*) transformbasename=`echo $1 | sed 's/-b=//'` shift continue;; *) if [ x"$src" = x ] then src=$1 else # this colon is to work around a 386BSD /bin/sh bug : dst=$1 fi shift continue;; esac done if [ x"$src" = x ] then echo "install: no input file specified" exit 1 else true fi if [ x"$dir_arg" != x ]; then dst=$src src="" if [ -d $dst ]; then instcmd=: chmodcmd="" else instcmd=mkdir fi else # Waiting for this to be detected by the "$instcmd $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if [ -f $src -o -d $src ] then true else echo "install: $src does not exist" exit 1 fi if [ x"$dst" = x ] then echo "install: no destination specified" exit 1 else true fi # If destination is a directory, append the input filename; if your system # does not like double slashes in filenames, you may need to add some logic if [ -d $dst ] then dst="$dst"/`basename $src` else true fi fi ## this sed command emulates the dirname command dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` # Make sure that the destination directory exists. # this part is taken from Noah Friedman's mkinstalldirs script # Skip lots of stat calls in the usual case. if [ ! -d "$dstdir" ]; then defaultIFS=' ' IFS="${IFS-${defaultIFS}}" oIFS="${IFS}" # Some sh's can't handle IFS=/ for some reason. IFS='%' set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` IFS="${oIFS}" pathcomp='' while [ $# -ne 0 ] ; do pathcomp="${pathcomp}${1}" shift if [ ! -d "${pathcomp}" ] ; then $mkdirprog "${pathcomp}" else true fi pathcomp="${pathcomp}/" done fi if [ x"$dir_arg" != x ] then $doit $instcmd $dst && if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi else # If we're going to rename the final executable, determine the name now. if [ x"$transformarg" = x ] then dstfile=`basename $dst` else dstfile=`basename $dst $transformbasename | sed $transformarg`$transformbasename fi # don't allow the sed command to completely eliminate the filename if [ x"$dstfile" = x ] then dstfile=`basename $dst` else true fi # Make a temp file name in the proper directory. dsttmp=$dstdir/#inst.$$# # Move or copy the file name to the temp name $doit $instcmd $src $dsttmp && trap "rm -f ${dsttmp}" 0 && # and set any options; do chmod last to preserve setuid bits # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $instcmd $src $dsttmp" command. if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && # Now rename the file to the real destination. $doit $rmcmd -f $dstdir/$dstfile && $doit $mvcmd $dsttmp $dstdir/$dstfile fi && exit 0 matanza-0.13/stamp-h.in0000644000175000017500000000001207263463453015146 0ustar boradminboradmintimestamp matanza-0.13/missing0000744000175000017500000001421307107673453014652 0ustar boradminboradmin#! /bin/sh # Common stub for a few missing GNU programs while installing. # Copyright (C) 1996, 1997 Free Software Foundation, Inc. # Franc,ois Pinard , 1996. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. if test $# -eq 0; then echo 1>&2 "Try \`$0 --help' for more information" exit 1 fi case "$1" in -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an error status if there is no known handling for PROGRAM. Options: -h, --help display this help and exit -v, --version output version information and exit Supported PROGRAM values: aclocal touch file \`aclocal.m4' autoconf touch file \`configure' autoheader touch file \`config.h.in' automake touch all \`Makefile.in' files bison create \`y.tab.[ch]', if possible, from existing .[ch] flex create \`lex.yy.c', if possible, from existing .c lex create \`lex.yy.c', if possible, from existing .c makeinfo touch the output file yacc create \`y.tab.[ch]', if possible, from existing .[ch]" ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing - GNU libit 0.0" ;; -*) echo 1>&2 "$0: Unknown \`$1' option" echo 1>&2 "Try \`$0 --help' for more information" exit 1 ;; aclocal) echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified \`acinclude.m4' or \`configure.in'. You might want to install the \`Automake' and \`Perl' packages. Grab them from any GNU archive site." touch aclocal.m4 ;; autoconf) echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified \`configure.in'. You might want to install the \`Autoconf' and \`GNU m4' packages. Grab them from any GNU archive site." touch configure ;; autoheader) echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified \`acconfig.h' or \`configure.in'. You might want to install the \`Autoconf' and \`GNU m4' packages. Grab them from any GNU archive site." files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' configure.in` test -z "$files" && files="config.h" touch_files= for f in $files; do case "$f" in *:*) touch_files="$touch_files "`echo "$f" | sed -e 's/^[^:]*://' -e 's/:.*//'`;; *) touch_files="$touch_files $f.in";; esac done touch $touch_files ;; automake) echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified \`Makefile.am', \`acinclude.m4' or \`configure.in'. You might want to install the \`Automake' and \`Perl' packages. Grab them from any GNU archive site." find . -type f -name Makefile.am -print | sed 's/\.am$/.in/' | while read f; do touch "$f"; done ;; bison|yacc) echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified a \`.y' file. You may need the \`Bison' package in order for those modifications to take effect. You can get \`Bison' from any GNU archive site." rm -f y.tab.c y.tab.h if [ $# -ne 1 ]; then eval LASTARG="\${$#}" case "$LASTARG" in *.y) SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` if [ -f "$SRCFILE" ]; then cp "$SRCFILE" y.tab.c fi SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` if [ -f "$SRCFILE" ]; then cp "$SRCFILE" y.tab.h fi ;; esac fi if [ ! -f y.tab.h ]; then echo >y.tab.h fi if [ ! -f y.tab.c ]; then echo 'main() { return 0; }' >y.tab.c fi ;; lex|flex) echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified a \`.l' file. You may need the \`Flex' package in order for those modifications to take effect. You can get \`Flex' from any GNU archive site." rm -f lex.yy.c if [ $# -ne 1 ]; then eval LASTARG="\${$#}" case "$LASTARG" in *.l) SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` if [ -f "$SRCFILE" ]; then cp "$SRCFILE" lex.yy.c fi ;; esac fi if [ ! -f lex.yy.c ]; then echo 'main() { return 0; }' >lex.yy.c fi ;; makeinfo) echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified a \`.texi' or \`.texinfo' file, or any other file indirectly affecting the aspect of the manual. The spurious call might also be the consequence of using a buggy \`make' (AIX, DU, IRIX). You might want to install the \`Texinfo' package or the \`GNU make' package. Grab either from any GNU archive site." file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` if test -z "$file"; then file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file` fi touch $file ;; *) echo 1>&2 "\ WARNING: \`$1' is needed, and you do not seem to have it handy on your system. You might have modified some files without having the proper tools for further handling them. Check the \`README' file, it often tells you about the needed prerequirements for installing this package. You may also peek at any GNU archive site, in case some other package would contain this missing \`$1' program." exit 1 ;; esac exit 0 matanza-0.13/xmlrole.h0000644000175000017500000000466707254521711015114 0ustar boradminboradmin/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd See the file copying.txt for copying permission. */ #ifndef XmlRole_INCLUDED #define XmlRole_INCLUDED 1 #include "xmltok.h" #ifdef __cplusplus extern "C" { #endif enum { XML_ROLE_ERROR = -1, XML_ROLE_NONE = 0, XML_ROLE_XML_DECL, XML_ROLE_INSTANCE_START, XML_ROLE_DOCTYPE_NAME, XML_ROLE_DOCTYPE_SYSTEM_ID, XML_ROLE_DOCTYPE_PUBLIC_ID, XML_ROLE_DOCTYPE_CLOSE, XML_ROLE_GENERAL_ENTITY_NAME, XML_ROLE_PARAM_ENTITY_NAME, XML_ROLE_ENTITY_VALUE, XML_ROLE_ENTITY_SYSTEM_ID, XML_ROLE_ENTITY_PUBLIC_ID, XML_ROLE_ENTITY_NOTATION_NAME, XML_ROLE_NOTATION_NAME, XML_ROLE_NOTATION_SYSTEM_ID, XML_ROLE_NOTATION_NO_SYSTEM_ID, XML_ROLE_NOTATION_PUBLIC_ID, XML_ROLE_ATTRIBUTE_NAME, XML_ROLE_ATTRIBUTE_TYPE_CDATA, XML_ROLE_ATTRIBUTE_TYPE_ID, XML_ROLE_ATTRIBUTE_TYPE_IDREF, XML_ROLE_ATTRIBUTE_TYPE_IDREFS, XML_ROLE_ATTRIBUTE_TYPE_ENTITY, XML_ROLE_ATTRIBUTE_TYPE_ENTITIES, XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN, XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS, XML_ROLE_ATTRIBUTE_ENUM_VALUE, XML_ROLE_ATTRIBUTE_NOTATION_VALUE, XML_ROLE_ATTLIST_ELEMENT_NAME, XML_ROLE_IMPLIED_ATTRIBUTE_VALUE, XML_ROLE_REQUIRED_ATTRIBUTE_VALUE, XML_ROLE_DEFAULT_ATTRIBUTE_VALUE, XML_ROLE_FIXED_ATTRIBUTE_VALUE, XML_ROLE_ELEMENT_NAME, XML_ROLE_CONTENT_ANY, XML_ROLE_CONTENT_EMPTY, XML_ROLE_CONTENT_PCDATA, XML_ROLE_GROUP_OPEN, XML_ROLE_GROUP_CLOSE, XML_ROLE_GROUP_CLOSE_REP, XML_ROLE_GROUP_CLOSE_OPT, XML_ROLE_GROUP_CLOSE_PLUS, XML_ROLE_GROUP_CHOICE, XML_ROLE_GROUP_SEQUENCE, XML_ROLE_CONTENT_ELEMENT, XML_ROLE_CONTENT_ELEMENT_REP, XML_ROLE_CONTENT_ELEMENT_OPT, XML_ROLE_CONTENT_ELEMENT_PLUS, #ifdef XML_DTD XML_ROLE_TEXT_DECL, XML_ROLE_IGNORE_SECT, XML_ROLE_INNER_PARAM_ENTITY_REF, #endif /* XML_DTD */ XML_ROLE_PARAM_ENTITY_REF, XML_ROLE_EXTERNAL_GENERAL_ENTITY_NO_NOTATION }; typedef struct prolog_state { int (*handler)(struct prolog_state *state, int tok, const char *ptr, const char *end, const ENCODING *enc); unsigned level; #ifdef XML_DTD unsigned includeLevel; int documentEntity; #endif /* XML_DTD */ } PROLOG_STATE; void XMLTOKAPI XmlPrologStateInit(PROLOG_STATE *); #ifdef XML_DTD void XMLTOKAPI XmlPrologStateInitExternalEntity(PROLOG_STATE *); #endif /* XML_DTD */ #define XmlTokenRole(state, tok, ptr, end, enc) \ (((state)->handler)(state, tok, ptr, end, enc)) #ifdef __cplusplus } #endif #endif /* not XmlRole_INCLUDED */