Updated build system and now bundle libb64

This commit is contained in:
Andrew Pamment
2017-03-18 14:37:16 +10:00
parent 3304fbf0fa
commit 7afb34fc61
131 changed files with 1249 additions and 55 deletions

19
deps/Xmodem/LICENSE vendored Normal file
View File

@@ -0,0 +1,19 @@
Copyright <20> 2001 Edward A. Falk
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

42
deps/Xmodem/Makefile vendored Normal file
View File

@@ -0,0 +1,42 @@
# $Id: Makefile,v 1.2 2001/10/25 23:56:29 efalk Exp $
INC = -I..
#OPT = -g
OPT = -O
CFLAGS = $(OPT) $(INC) -DHAVE_STRDUP
AR = ar
RANLIB = ranlib
HDRS = crctab.h seriallog.h xmodem.h zmodem.h
SRCS = crctab.c seriallog.c zmodem.c zmodemr.c zmodemsys.c zmodemt.c zmutil.c
OBJS = $(SRCS:.c=.o)
libzmodem.a: $(OBJS)
-rm -f libzmodem.a
$(AR) cru libzmodem.a $(OBJS)
$(RANLIB) libzmodem.a
clean:
rm -f *.o *.s *.i
clobber: clean
rm -f *.a tags
tags: $(SRCS) $(HDRS)
ctags *.[ch]
.SUFFIXES: .i .s
.c.i:
$(CC) -E $(CFLAGS) $*.c > $@
.c.s:
$(CC) -S $(CFLAGS) $*.c
depend:
makedepend -- $(CFLAGS) -- $(SRCS)

197
deps/Xmodem/checkcrc.c vendored Normal file
View File

@@ -0,0 +1,197 @@
#ifndef lint
static const char rcsid[] = "$Id: checkcrc.c,v 1.2 2001/10/25 23:56:29 efalk Exp $" ;
#endif
#include <stdio.h>
#include <sys/types.h>
#include "crctab.h"
static u_char msg0[] = {
0x2a, 0x18, 0x43, 0x0a, 0x00, 0x00, 0x00, 0x00,
0xbc, 0xef, 0x92, 0x8c,} ;
static u_char msg0c[] = {
0x2a, 0x18, 0x43, 0x0a, 0x00, 0x00, 0x00, 0x00,
0xbc, 0xef, 0x92, 0x8c, 0x0b, 0xdf,} ;
static u_char msg1[] = {
0x0a, 0x23, 0x69, 0x6e,
0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x3c, 0x73,
0x79, 0x73, 0x2f, 0x74, 0x65, 0x72, 0x6d, 0x69,
0x6f, 0x73, 0x2e, 0x68, 0x3e, 0x0a, 0x23, 0x69,
0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x22,
0x78, 0x6d, 0x6f, 0x64, 0x65, 0x6d, 0x2e, 0x68,
0x22, 0x0a, 0x0a, 0x0a, 0x69, 0x6e, 0x74, 0x0a,
0x73, 0x65, 0x6e, 0x64, 0x43, 0x61, 0x6e, 0x63,
0x65, 0x6c, 0x28, 0x29, 0x0a, 0x7b, 0x0a, 0x09,
0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x73,
0x65, 0x6e, 0x64, 0x46, 0x6c, 0x75, 0x73, 0x68,
0x28, 0x43, 0x41, 0x4e, 0x29, 0x20, 0x7c, 0x7c,
0x20, 0x73, 0x65, 0x6e, 0x64, 0x46, 0x6c, 0x75,
0x73, 0x68, 0x28, 0x43, 0x41, 0x4e, 0x29, 0x20,
0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x0a, 0x09, 0x2f,
0x2a, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6f,
0x6e, 0x65, 0x20, 0x63, 0x68, 0x61, 0x72, 0x61,
0x63, 0x74, 0x65, 0x72, 0x2c, 0x20, 0x72, 0x65,
0x74, 0x75, 0x72, 0x6e, 0x20, 0x6e, 0x6f, 0x6e,
0x7a, 0x65, 0x72, 0x6f, 0x20, 0x6f, 0x6e, 0x20,
0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x2a, 0x2f,
0x0a, 0x69, 0x6e, 0x74, 0x0a, 0x73, 0x65, 0x6e,
0x64, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x28, 0x63,
0x29, 0x0a, 0x09, 0x63, 0x68, 0x61, 0x72, 0x09,
0x63, 0x20, 0x3b, 0x0a, 0x7b, 0x0a, 0x09, 0x2f,
0x2a, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x2c,
0x20, 0x66, 0x6c, 0x75, 0x73, 0x68, 0x20, 0x69,
0x6e, 0x70, 0x75, 0x74, 0x20, 0x70, 0x6f, 0x72,
0x74, 0x20, 0x2a, 0x2f, 0x0a, 0x09, 0x2f, 0x2a,
0x20, 0x54, 0x4f, 0x44, 0x4f, 0x3a, 0x20, 0x63,
0x61, 0x6c, 0x6c, 0x65, 0x72, 0x20, 0x70, 0x72,
0x6f, 0x76, 0x69, 0x64, 0x65, 0x20, 0x61, 0x20,
0x77, 0x61, 0x79, 0x20, 0x18, 0x69, 0x4c, 0x5b,
0x62, 0x0f,
0x2a, 0x18, 0x43, 0x0a, 0x00, 0x00,
0x00, 0x00, 0xbc, 0xef, 0x92, 0x8c, 0x0a, 0x23,
0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20,
0x3c, 0x73, 0x79, 0x73, 0x2f, 0x74, 0x65, 0x72,
0x6d, 0x69, 0x6f, 0x73, 0x2e, 0x68, 0x3e, 0x0a,
0x23, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65,
0x20, 0x22, 0x78, 0x6d, 0x6f, 0x64, 0x65, 0x6d,
0x2e, 0x68, 0x22, 0x0a, 0x0a, 0x0a, 0x69, 0x6e,
0x74, 0x0a, 0x73, 0x65, 0x6e, 0x64, 0x43, 0x61,
0x6e, 0x63, 0x65, 0x6c, 0x28, 0x29, 0x0a, 0x7b,
0x0a, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e,
0x20, 0x73, 0x65, 0x6e, 0x64, 0x46, 0x6c, 0x75,
0x73, 0x68, 0x28, 0x43, 0x41, 0x4e, 0x29, 0x20,
0x7c, 0x7c, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x46,
0x6c, 0x75, 0x73, 0x68, 0x28, 0x43, 0x41, 0x4e,
0x29, 0x20, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x0a,
0x09, 0x2f, 0x2a, 0x20, 0x73, 0x65, 0x6e, 0x64,
0x20, 0x6f, 0x6e, 0x65, 0x20, 0x63, 0x68, 0x61,
0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x2c, 0x20,
0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6e,
0x6f, 0x6e, 0x7a, 0x65, 0x72, 0x6f, 0x20, 0x6f,
0x6e, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20,
0x2a, 0x2f, 0x0a, 0x69, 0x6e, 0x74, 0x0a, 0x73,
0x65, 0x6e, 0x64, 0x46, 0x6c, 0x75, 0x73, 0x68,
0x28, 0x63, 0x29, 0x0a, 0x09, 0x63, 0x68, 0x61,
0x72, 0x09, 0x63, 0x20, 0x3b, 0x0a, 0x7b, 0x0a,
0x09, 0x2f, 0x2a, 0x20, 0x66, 0x69, 0x72, 0x73,
0x74, 0x2c, 0x20, 0x66, 0x6c, 0x75, 0x73, 0x68,
0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x70,
0x6f, 0x72, 0x74, 0x20, 0x2a, 0x2f, 0x0a, 0x09,
0x2f, 0x2a, 0x20, 0x54, 0x4f, 0x44, 0x4f, 0x3a,
0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x20,
0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x20,
0x61, 0x20, 0x77, 0x61, 0x79, 0x20, 0x18, 0x6b,
0x60, 0x3a, 0x6c, 0xe1,
} ;
static u_char msg2[] = {1} ;
#ifdef COMMENT
#define updcrc(cp, crc) ( crctab[((crc >> 8) & 255)] ^ (crc << 8) ^ cp)
#define updcrc(cp, crc) ( crctab[((crc>>8)^cp) & 255] ^ (crc<<8) )
#endif /* COMMENT */
static int addcrc(int data, int crc) ;
main()
{
u_short crc16 ;
u_long crc32 ;
int i,j ;
u_long k ;
u_char *msg = msg0 ;
int len = sizeof(msg0) ;
/* crc16 of message */
crc16 = 0 ;
crc32 = 0xffffffff ;
for(i=0; i<len; ++i)
{
crc16 = addcrc(msg[i], crc16) ;
}
printf("crc16=%4.4hx, ~crc16=%4.4hx\n", crc16, ~crc16&0xffff) ;
crc16 = addcrc(0, crc16) ;
crc16 = addcrc(0, crc16) ;
printf("crc16=%4.4hx, ~crc16=%4.4hx\n", crc16, ~crc16&0xffff) ;
/* crc of reception */
j = crc16 ;
crc16 = 0 ;
crc32 = 0xffffffff ;
for(i=0; i<len; ++i)
{
crc16 = addcrc(msg[i], crc16) ;
}
printf("crc16=%4.4hx, ~crc16=%4.4hx\n", crc16, ~crc16&0xffff) ;
crc16 = addcrc(j>>8, crc16) ;
crc16 = addcrc(j&0xff, crc16) ;
printf("crc16=%4.4hx, ~crc16=%4.4hx\n", crc16, ~crc16&0xffff) ;
#ifdef COMMENT
crc16 = 0 ;
crc32 = 0xffffffff ;
for(i=0; i<len; ++i)
{
crc16 = updcrc(msg[i], crc16) ;
crc32 = UPDC32(msg[i], crc32) ;
printf("%4.4x\n", crc16) ;
}
printf("crc16=%4.4hx, ~crc16=%4.4hx\n", crc16, ~crc16&0xffff) ;
printf("crc32=%8.8x, ~crc=%8.8x\n", crc32,~crc32) ;
#ifdef COMMENT
printf("\n") ;
printf("%2.2x\n", crc16&0xff) ;
printf("%2.2x\n", crc16>>8) ;
#endif /* COMMENT */
i = crc16 ;
crc16 = updcrc(i&0xff, crc16) ;
crc16 = updcrc(i>>8, crc16) ;
k = ~crc32 ;
crc32 = updcrc(k&0xff, crc32) ;
crc32 = updcrc((k>>8)&0xff, crc32) ;
crc32 = updcrc((k>>16)&0xff, crc32) ;
crc32 = updcrc((k>>24)&0xff, crc32) ;
printf("crc16=%4.4hx, ~crc16=%4.4hx\n", crc16, ~crc16&0xffff) ;
printf("crc32=%8.8x, ~crc=%8.8x\n", crc32,~crc32) ;
#endif /* COMMENT */
exit(0) ;
}
static int
addcrc(int data, int crc)
{
int j ;
crc ^= (unsigned short) data<<8;
for(j=0; j<8; ++j) {
if( crc & 0x8000 )
crc = (crc<<1) ^ 0x1021;
else
crc <<= 1 ;
}
return crc & 0xffff ;
}

182
deps/Xmodem/crc.c vendored Normal file
View File

@@ -0,0 +1,182 @@
#ifndef lint
static const char rcsid[] = "$Id: crc.c,v 1.2 2001/10/25 23:56:29 efalk Exp $" ;
#endif
/*% cc -O -K -dos % -o crc.exe
*/
/*
* Crc - 32 BIT ANSI X3.66 CRC checksum files
*/
#include <stdio.h>
#define OK 0
#define ERROR (-1)
#define LINT_ARGS
/**********************************************************************\
|* *|
|* Demonstration program to compute the 32-bit CRC used as the frame *|
|* check sequence in ADCCP (ANSI X3.66, also known as FIPS PUB 71 *|
|* and FED-STD-1003, the U.S. versions of CCITT's X.25 link-level *|
|* protocol). The 32-bit FCS was added via the Federal Register, *|
|* 1 June 1982, p.23798. I presume but don't know for certain that *|
|* this polynomial is or will be included in CCITT V.41, which *|
|* defines the 16-bit CRC (often called CRC-CCITT) polynomial. FIPS *|
|* PUB 78 says that the 32-bit FCS reduces otherwise undetected *|
|* errors by a factor of 10^-5 over 16-bit FCS. *|
|* *|
\**********************************************************************/
/* Need an unsigned type capable of holding 32 bits; */
typedef unsigned long int UNS_32_BITS;
/*
* Copyright (C) 1986 Gary S. Brown. You may use this program, or
* code or tables extracted from it, as desired without restriction.
*/
/* First, the polynomial itself and its table of feedback terms. The */
/* polynomial is */
/* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */
/* Note that we take it "backwards" and put the highest-order term in */
/* the lowest-order bit. The X^32 term is "implied"; the LSB is the */
/* X^31 term, etc. The X^0 term (usually shown as "+1") results in */
/* the MSB being 1. */
/* Note that the usual hardware shift register implementation, which */
/* is what we're using (we're merely optimizing it by doing eight-bit */
/* chunks at a time) shifts bits into the lowest-order term. In our */
/* implementation, that means shifting towards the right. Why do we */
/* do it this way? Because the calculated CRC must be transmitted in */
/* order from highest-order term to lowest-order term. UARTs transmit */
/* characters in order from LSB to MSB. By storing the CRC this way, */
/* we hand it to the UART in the order low-byte to high-byte; the UART */
/* sends each low-bit to hight-bit; and the result is transmission bit */
/* by bit from highest- to lowest-order term without requiring any bit */
/* shuffling on our part. Reception works similarly. */
/* The feedback terms table consists of 256, 32-bit entries. Notes: */
/* */
/* 1. The table can be generated at runtime if desired; code to do so */
/* is shown later. It might not be obvious, but the feedback */
/* terms simply represent the results of eight shift/xor opera- */
/* tions for all combinations of data and CRC register values. */
/* */
/* 2. The CRC accumulation logic is the same for all CRC polynomials, */
/* be they sixteen or thirty-two bits wide. You simply choose the */
/* appropriate table. Alternatively, because the table can be */
/* generated at runtime, you can start by generating the table for */
/* the polynomial in question and use exactly the same "updcrc", */
/* if your application needn't simultaneously handle two CRC */
/* polynomials. (Note, however, that XMODEM is strange.) */
/* */
/* 3. For 16-bit CRCs, the table entries need be only 16 bits wide; */
/* of course, 32-bit entries work OK if the high 16 bits are zero. */
/* */
/* 4. The values must be right-shifted by eight bits by the "updcrc" */
/* logic; the shift must be unsigned (bring in zeroes). On some */
/* hardware you could probably optimize the shift in assembler by */
/* using byte-swap instructions. */
static UNS_32_BITS crc_32_tab[] = { /* CRC polynomial 0xedb88320 */
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
#define UPDC32(octet, crc) (crc_32_tab[((crc) ^ (octet)) & 0xff] ^ ((crc) >> 8))
int Block = 0; /* Pad file with 032's to multiple of Block */
main(argc, argv)
char **argv;
{
register errors = 0;
if (! strcmp(argv[1], "-x")) {
Block = 128; --argc; ++argv;
}
if (! strcmp(argv[1], "-k")) {
Block = 1024; --argc; ++argv;
}
while( --argc > 0)
errors |= crc32file( *++argv);
exit(errors != 0);
}
crc32file(name)
char *name;
{
register FILE *fin;
register unsigned long oldcrc32;
register unsigned long crc32;
register unsigned long oldcrc;
register c;
register long charcnt;
register long l;
oldcrc32 = 0xFFFFFFFF; charcnt = 0;
#ifdef M_I86SM
if ((fin=fopen(name, "rb"))==NULL)
#else
if ((fin=fopen(name, "r"))==NULL)
#endif
{
perror(name);
return ERROR;
}
while ((c=getc(fin))!=EOF) {
++charcnt;
oldcrc32 = UPDC32(c, oldcrc32);
}
if (ferror(fin)) {
perror(name);
fclose(fin); return ERROR;
}
else {
if (Block) {
for (l = charcnt; l % Block; ++l)
oldcrc32 = UPDC32(032, oldcrc32);
}
crc32 = oldcrc32; oldcrc = oldcrc32 = ~oldcrc32;
printf("%08lX %7ld ", oldcrc, charcnt);
if (Block == 128)
printf("%5ld+%3ld ", charcnt/Block, charcnt%Block);
if (Block == 1024)
printf("%5ld+%4ld ", charcnt/Block, charcnt%Block);
printf(" %s\n", name);
}
fclose(fin); return OK;
}

154
deps/Xmodem/crctab.c vendored Normal file
View File

@@ -0,0 +1,154 @@
#ifndef lint
static const char rcsid[] = "$Id: crctab.c,v 1.2 2001/10/25 23:56:29 efalk Exp $" ;
#endif
/*
* Crc calculation stuff
*/
/* crctab calculated by Mark G. Mendel, Network Systems Corporation */
unsigned short crctab[256] = {
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
};
/*
* updcrc macro derived from article Copyright (C) 1986 Stephen Satchell.
* NOTE: First argument must be in range 0 to 255.
* Second argument is referenced twice.
*
* Programmers may incorporate any or all code into their programs,
* giving proper credit within the source. Publication of the
* source routines is permitted so long as proper credit is given
* to Stephen Satchell, Satchell Evaluations and Chuck Forsberg,
* Omen Technology.
*/
#define updcrc(cp, crc) ( crctab[((crc >> 8) & 255)] ^ (crc << 8) ^ cp)
/*
* Copyright (C) 1986 Gary S. Brown. You may use this program, or
* code or tables extracted from it, as desired without restriction.
*/
/* First, the polynomial itself and its table of feedback terms. The */
/* polynomial is */
/* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */
/* Note that we take it "backwards" and put the highest-order term in */
/* the lowest-order bit. The X^32 term is "implied"; the LSB is the */
/* X^31 term, etc. The X^0 term (usually shown as "+1") results in */
/* the MSB being 1. */
/* Note that the usual hardware shift register implementation, which */
/* is what we're using (we're merely optimizing it by doing eight-bit */
/* chunks at a time) shifts bits into the lowest-order term. In our */
/* implementation, that means shifting towards the right. Why do we */
/* do it this way? Because the calculated CRC must be transmitted in */
/* order from highest-order term to lowest-order term. UARTs transmit */
/* characters in order from LSB to MSB. By storing the CRC this way, */
/* we hand it to the UART in the order low-byte to high-byte; the UART */
/* sends each low-bit to hight-bit; and the result is transmission bit */
/* by bit from highest- to lowest-order term without requiring any bit */
/* shuffling on our part. Reception works similarly. */
/* The feedback terms table consists of 256, 32-bit entries. Notes: */
/* */
/* The table can be generated at runtime if desired; code to do so */
/* is shown later. It might not be obvious, but the feedback */
/* terms simply represent the results of eight shift/xor opera- */
/* tions for all combinations of data and CRC register values. */
/* */
/* The values must be right-shifted by eight bits by the "updcrc" */
/* logic; the shift must be unsigned (bring in zeroes). On some */
/* hardware you could probably optimize the shift in assembler by */
/* using byte-swap instructions. */
unsigned long cr3tab[] = { /* CRC polynomial 0xedb88320 */
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d };
#ifdef NFGM
long
UPDC32(b, c)
long c;
{
return (cr3tab[((int)c ^ b) & 0xff] ^ ((c >> 8) & 0x00FFFFFF));
}
#else
#define UPDC32(b, c) (cr3tab[((int)c ^ b) & 0xff] ^ ((c >> 8) & 0x00FFFFFF))
#endif
/* End of crctab.c */

13
deps/Xmodem/crctab.h vendored Normal file
View File

@@ -0,0 +1,13 @@
/* @(#)crctab.h 1.2 96/09/13 */
/*
* Crc calculation stuff. See crctab.c
*/
extern unsigned short crctab[256] ;
#define updcrc(cp, crc) ( crctab[((crc >> 8) & 255)] ^ (crc << 8) ^ cp)
extern unsigned long cr3tab[] ;
#define UPDC32(b, c) (cr3tab[((int)c ^ b) & 0xff] ^ ((c >> 8) & 0x00FFFFFF))

913
deps/Xmodem/main.c vendored Normal file
View File

@@ -0,0 +1,913 @@
#ifndef lint
static const char rcsid[] = "$Id: main.c,v 1.1.1.1 2001/03/08 00:01:48 efalk Exp $" ;
#endif
/*
* Copyright (c) 1995 by Edward A. Falk
*/
/**********
*
*
* @ @ @@@ @@@ @ @
* @@ @@ @ @ @ @@ @
* @ @ @ @@@@@ @ @ @ @
* @ @ @ @ @ @ @ @@
* @ @ @ @ @ @@@ @ @
*
* MAIN - demonstration zmodem program
*
* This program implements the x,y,z-modem protocols, using the
* zmodem library.
*
* Edward A. Falk
*
* Jan, 1995
*
*
*
**********/
static char usage [] =
"usage: zmodem -r [options]\n\
zmodem -s [options] file [file ...]\n\
-r receive files\n\
-s send files\n\
- file allows you to transmit files with '-' in their names\n\
-v verbose, more v's increase messages.\n\
-l /dev/ttyX use specified serial port instead of /dev/tty\n\
-b baud set baud rate\n\
-x file use xmodem, specify filename\n\
-y use ymodem\n\
-k use 1k, packets (ymodem, xmodem)\n\
-win nn set sliding window to nn bytes (send)\n\
-buf nn set input buffer size to nn bytes (receive)\n\
-L nn set packet length\n\
-e escape control characters\n\
-a ascii text\n\
-i image (binary data)\n\
-resume continue an interrupted transfer\n\
-new transfer only if newer\n\
-newl transfer only if newer or longer\n\
-diff transfer only if dates or lengths differ\n\
-crc transfer only if length or crc different\n\
-apnd append to existing file\n\
-clob force overwrite of existing files\n\
-prot do not overwrite existing files\n\
-chng change filename if destination exists\n\
-noloc do not transfer unless destination exists\n\
-[hq] this list\n" ;
#include <stdio.h>
/****
*
* Constants, typedefs, externals, globals, statics, macros, block data
*
****/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/stat.h>
#include <signal.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/time.h>
#include <sys/termios.h>
#include <sys/param.h>
#include "zmodem.h"
#include "seriallog.h"
extern int errno ;
extern char *getenv() ;
/* compile-time parameters */
#define ESCCTRL 0 /* control characters need to be escaped */
#if !defined(CRTSCTS) && defined(CNEW_RTSCTS)
#define CRTSCTS CNEW_RTSCTS
#endif
static int baud = 0 ; /* requested baud rate */
static char *line = NULL ; /* requested serial line */
static int verbose = 0 ;
static int send = 0 ; /* send files */
static int receive = 0 ; /* receive */
static int xmodem = 0 ; /* use xmodem */
static int ymodem = 0 ; /* use ymodem */
static int escCtrl = ESCCTRL ;
static int ascii = 0 ; /* translate line endings */
static int binary = 0 ; /* don't translate line endings */
static int resume = 0 ; /* resume interrupted transfers */
static int xferType = 0 ; /* new,newl,diff,crc, etc. */
static int noloc = 0 ;
static int doCancel = 0 ;
static int doLogging = 0 ;
static int Corrupt = 0 ; /* deliberately corrupt data */
static int fileErrs ; /* used to track errors per file */
static int fileSent ; /* track amount sent */
static ZModem info ;
static int begun = 0 ;
static struct termios old_settings, new_settings ;
static int FinishXmit(ZModem *info) ;
static int DoReceive(ZModem *info) ;
static int InitXmit(ZModem *info) ;
static int XmitFile(char *filename, int f0, int f1, ZModem *info) ;
static void SendFile() ;
static void RcvFiles() ;
static void RcvXmodem() ;
static int getBaud() ;
static void resetCom() ;
static char *basename(char *name) ;
#ifdef SVr4
static void sighandle(int) ;
#else
static void sighandle() ;
#endif
extern FILE *SerialLogFile ;
extern FILE *zmodemlogfile ;
int
main(int argc, char **argv)
{
char *progname ;
#ifdef COMMENT
printf("%d\n", getpid()) ;
#endif /* COMMENT */
info.ifd = info.ofd = -1 ;
info.zrinitflags = 0 ;
info.zsinitflags = 0 ;
info.attn = NULL ;
info.packetsize = 0 ;
info.windowsize = 0 ;
info.bufsize = 0 ;
progname = basename(argv[0]) ;
if( strcmp(progname,"rz") == 0 )
receive = 1 ;
else if( strcmp(progname, "sz") == 0 )
send = 1 ;
++argv, --argc ; /* skip program name */
/* parse options */
for(; argc > 0 && **argv == '-'; ++argv, --argc )
{
if( strcmp(*argv, "-r") == 0 )
receive = 1 ;
else if( strcmp(*argv, "-s") == 0 )
send = 1 ;
else if( strncmp(*argv, "-v", 2) == 0 )
verbose += strlen(*argv)+1 ;
else if( strcmp(*argv, "-l") == 0 && --argc > 0 )
line = *++argv ;
else if( strcmp(*argv, "-b") == 0 && --argc > 0 )
baud = getBaud(atoi(*++argv)) ;
else if( strcmp(*argv, "-x") == 0 )
xmodem = 1 ;
else if( strcmp(*argv, "-y") == 0 )
ymodem = 1 ;
else if( strcmp(*argv, "-win") == 0 && --argc > 0 )
info.windowsize = atoi(*++argv) ;
else if( strcmp(*argv, "-buf") == 0 && --argc > 0 )
info.bufsize = atoi(*++argv) ;
else if( strcmp(*argv, "-L") == 0 && --argc > 0 )
info.packetsize = atoi(*++argv) ;
else if( strcmp(*argv, "-k") == 0 )
info.packetsize = 1024 ;
else if( strcmp(*argv, "-e") == 0 )
escCtrl = ESCCTL ;
else if( strcmp(*argv, "-a") == 0 )
ascii = 1 ;
else if( strcmp(*argv, "-i") == 0 )
binary = 1 ;
else if( strcmp(*argv, "-resume") == 0 )
resume = 1 ;
else if( strcmp(*argv, "-new") == 0 )
xferType = ZMNEW ;
else if( strcmp(*argv, "-newl") == 0 )
xferType = ZMNEWL ;
else if( strcmp(*argv, "-diff") == 0 )
xferType = ZMDIFF ;
else if( strcmp(*argv, "-crc") == 0 )
xferType = ZMCRC ;
else if( strcmp(*argv, "-apnd") == 0 )
xferType = ZMAPND ;
else if( strcmp(*argv, "-clob") == 0 )
xferType = ZMCLOB ;
else if( strcmp(*argv, "-prot") == 0 )
xferType = ZMPROT ;
else if( strcmp(*argv, "-chng") == 0 )
xferType = ZMCHNG ;
else if( strcmp(*argv, "-noloc") == 0 )
noloc = ZMSKNOLOC ;
else if( strcmp(*argv, "-h") == 0 ||
strcmp(*argv, "-q") == 0 )
{
fprintf(stderr, usage) ;
exit(0) ;
}
else if( strcmp(*argv, "-corrupt") == 0 )
Corrupt = 1 ;
else if( strcmp(*argv, "-log") == 0 )
doLogging = 1 ;
else if( strcmp(*argv, "-") == 0 ) {
++argv, --argc ; break ;
}
else {
fprintf(stderr, "unknown argument '%s' or missing value\n%s",
*argv, usage) ;
exit(2) ;
}
}
if( doLogging ) {
if( (SerialLogFile = fopen("xfer.log", "w")) == NULL )
perror("xfer.log") ;
if( (zmodemlogfile = fopen("zmodem.log","w")) == NULL )
perror("zmodem.log") ;
}
if( send ) {
for(; argc > 0; ++argv, --argc ) /* process filenames */
SendFile(*argv) ;
FinishXmit(&info) ;
}
else if( receive )
{
if( !xmodem )
RcvFiles() ;
else
for(; argc > 0; ++argv, --argc ) /* process filenames */
RcvXmodem(*argv) ;
}
else {
fprintf(stderr,
"either -s (send) or -r (receive) must be specified\n%s", usage) ;
exit(2) ;
}
resetCom() ;
exit(0) ;
}
static void
sighandle(int arg)
{
doCancel = 1 ;
}
static void
openCom()
{
char *ptr ;
if( line == NULL )
line = getenv("RZSZLINE") ;
if( baud == 0 && (ptr = getenv("RZSZBAUD")) != NULL )
baud = getBaud(atoi(ptr)) ;
if( line == NULL ) {
info.ifd = 0 ;
info.ofd = 1 ;
}
else if( (info.ifd = info.ofd = open(line, O_RDWR)) == -1 ) {
fprintf(stderr,
"cannot open %s, %s, use \"zmodem -h\" for more info\n",
line, strerror(errno)) ;
exit(2) ;
}
/* assumption: setting attributes for one half of channel will
* change both halves. This fails if different physical
* devices are used.
*/
tcgetattr(info.ifd,&old_settings) ;
new_settings = old_settings ;
#ifdef IUCLC
new_settings.c_iflag &=
~(ISTRIP|INLCR|IGNCR|ICRNL|IUCLC|IXON|IXOFF|IMAXBEL) ;
#else
new_settings.c_iflag &=
~(ISTRIP|INLCR|IGNCR|ICRNL|IXON|IXOFF|IMAXBEL) ;
#endif
new_settings.c_oflag &= ~OPOST ;
new_settings.c_cflag &= ~(CSIZE|PARENB) ;
new_settings.c_cflag |= CS8 ;
if( baud != 0 ) {
cfsetospeed(&new_settings, baud) ;
cfsetispeed(&new_settings, baud) ;
}
else
baud = cfgetospeed(&old_settings) ;
new_settings.c_lflag = 0 ;
new_settings.c_cc[VMIN] = 32 ;
new_settings.c_cc[VTIME] = 1 ;
tcsetattr(info.ifd,TCSADRAIN, &new_settings) ;
info.zrinitflags = CANFDX|CANOVIO|CANBRK|CANFC32|escCtrl ;
info.zsinitflags = escCtrl ;
if( info.packetsize == 0 ) {
if( xmodem || ymodem )
info.packetsize = 128 ;
/* TODO: what about future high-speed interfaces? */
else if( baud < B2400 )
info.packetsize = 256 ;
else if( baud == B2400 )
info.packetsize = 512 ;
else
info.packetsize = 1024 ;
}
}
static void
resetCom()
{
tcsetattr(info.ifd,TCSADRAIN, &old_settings) ;
}
static void
SendFile(char *filename)
{
int f0, f1 ;
fileErrs = 0 ;
if( !begun ) /* establish connection */
{
openCom() ;
signal(SIGINT, sighandle) ;
signal(SIGTERM, sighandle) ;
signal(SIGHUP, sighandle) ;
if( InitXmit(&info) ) {
fprintf(stderr, "connect failed\n") ;
resetCom() ;
exit(1) ;
}
begun = 1 ;
}
if( ascii )
f0 = ZCNL ;
else if( binary )
f0 = ZCBIN ;
else if( resume )
f0 = ZCRESUM ;
else
f0 = 0 ;
f1 = xferType | noloc ;
if( XmitFile(filename, f0,f1, &info) ) {
fprintf(stderr, "connect failed\n") ;
resetCom() ;
exit(1) ;
}
}
static void
RcvFiles()
{
openCom() ;
signal(SIGINT, sighandle) ;
signal(SIGTERM, sighandle) ;
if( DoReceive(&info) ) {
fprintf(stderr, "connect failed\n") ;
resetCom() ;
exit(1) ;
}
}
static void
RcvXmodem(char *filename)
{
/* TODO: */
}
static int
getBaud(int b)
{
switch(b) {
case 50: return B50 ;
case 75: return B75 ;
case 110: return B110 ;
case 134: return B134 ;
case 150: return B150 ;
case 200: return B200 ;
case 300: return B300 ;
case 600: return B600 ;
case 1200: return B1200 ;
case 1800: return B1800 ;
case 2400: return B2400 ;
case 4800: return B4800 ;
case 9600: return B9600 ;
case 19200: return B19200 ;
case 38400: return B38400 ;
default: return 0 ;
}
}
/* TEST: randomly corrupt every 1000th byte */
static void
corrupt(u_char *buffer, int len)
{
extern double drand48() ;
while( --len >= 0 ) {
if( drand48() < 1./1000. )
*buffer ^= 0x81 ;
++buffer ;
}
}
static int
doIO(ZModem *info)
{
fd_set readfds ;
struct timeval timeout ;
int i ;
int len ;
u_char buffer[1024] ;
int done = 0 ;
while(!done)
{
FD_ZERO(&readfds) ;
FD_SET(info->ifd, &readfds) ;
timeout.tv_sec = info->timeout ;
timeout.tv_usec = 0 ;
i = select(info->ifd+1, &readfds,NULL,NULL, &timeout) ;
if( doCancel ) {
ZmodemAbort(info) ;
fprintf(stderr, "cancelled by user\n") ;
resetCom() ;
exit(3) ;
}
if( i<0 )
perror("select") ;
else if( i==0 )
done = ZmodemTimeout(info) ;
else {
len = read(info->ifd, buffer, sizeof(buffer)) ;
if( Corrupt )
corrupt(buffer, len) ;
if( SerialLogFile != NULL )
SerialLog(buffer, len, 1) ;
done = ZmodemRcv(buffer, len, info) ;
}
}
if( SerialLogFile != NULL )
SerialLogFlush() ;
return done ;
}
static int
InitXmit(ZModem *info)
{
int done ;
if( xmodem )
done = XmodemTInit(info) ;
else if( ymodem )
done = YmodemTInit(info) ;
else
done = ZmodemTInit(info) ;
if( !done )
done = doIO(info) ;
return done != ZmDone ;
}
static int
XmitFile(char *filename, int f0, int f1, ZModem *info)
{
int done ;
done = ZmodemTFile(filename,filename, f0,f1,0,0,
0,0, info) ;
switch( done ) {
case 0:
if( verbose )
fprintf(stderr, "Sending: \"%s\"\n", filename) ;
break ;
case ZmErrCantOpen:
fprintf(stderr, "cannot open file \"%s\": %s\n",
filename, strerror(errno)) ;
return 0 ;
case ZmFileTooLong:
fprintf(stderr, "filename \"%s\" too long, skipping...\n",
filename) ;
return 0 ;
case ZmDone:
return 0 ;
default:
return 1 ;
}
if( !done )
done = doIO(info) ;
return done != ZmDone ;
}
static int
FinishXmit(ZModem *info)
{
int done ;
done = ZmodemTFinish(info) ;
if( !done )
done = doIO(info) ;
return done != ZmDone ;
}
static int
DoReceive(ZModem *info)
{
int done ;
if( ymodem )
done = YmodemRInit(info) ;
else
done = ZmodemRInit(info) ;
if( !done )
done = doIO(info) ;
return done != ZmDone ;
}
int
ZXmitStr(u_char *buffer, int len, ZModem *info)
{
u_char b2[1024] ;
/* TEST: randomly corrupt every 1000th byte */
if( Corrupt )
{
bcopy(buffer, b2, len) ;
corrupt(b2, len) ;
buffer = b2 ;
}
if( SerialLogFile != NULL )
SerialLog(buffer, len, 0) ;
if( write(info->ofd, buffer, len) != len )
return ZmErrSys ;
return 0 ;
}
void
ZIFlush(ZModem *info)
{
if( SerialLogFile != NULL )
SerialLogFlush() ;
if( tcflush(info->ifd, TCIFLUSH) != 0 )
perror("TCIFLUSH") ;
}
void
ZOFlush(ZModem *info)
{
if( SerialLogFile != NULL )
SerialLogFlush() ;
if( tcflush(info->ifd, TCOFLUSH) != 0 )
perror("TCOFLUSH") ;
}
void
ZStatus(int type, int j, char *str)
{
switch( type ) {
case RcvByteCount:
if( verbose >= 2 )
fprintf(stderr, "received: %6d bytes\n", j) ;
break ;
case SndByteCount:
fileSent = j ;
if( verbose >= 2 )
fprintf(stderr, "sent: %6d bytes\n", j) ;
break ;
case RcvTimeout:
if( verbose )
fprintf(stderr, "receiver timeouts: %2d\n", j) ;
break ;
case SndTimeout:
if( verbose )
fprintf(stderr, "sender timeouts: %2d\n", j) ;
break ;
case RmtCancel:
fprintf(stderr, "transfer cancelled by remote\n") ;
break ;
case ProtocolErr:
if( verbose >= 3 )
fprintf(stderr, "protocol error: %2.2d\n", j) ;
break ;
case RemoteMessage:
fprintf(stderr, "remote message: %s\n",str) ;
break ;
case DataErr:
if( verbose >= 3 )
fprintf(stderr, "data errors: %2d\n", j) ;
#ifdef COMMENT
if( ++fileErrs > 20 )
{
/* something's wrong */
ZmodemAbort(&info) ;
}
#endif /* COMMENT */
break ;
case FileErr:
fprintf(stderr, "cannot write file: %s\n", strerror(errno)) ;
break ;
}
}
int
ZAttn(ZModem *info)
{
char *ptr ;
if( info->attn == NULL )
return 0 ;
for(ptr = info->attn; *ptr != '\0'; ++ptr) {
if( *ptr == ATTNBRK )
tcsendbreak(info->ifd, 0) ;
else if( *ptr == ATTNPSE )
sleep(1) ;
else
write(info->ifd, ptr, 1) ;
}
return 0 ;
}
FILE *
ZOpenFile(char *name, u_long crc, ZModem *info)
{
struct stat buf ;
int exists ; /* file already exists */
static int changeCount = 0 ;
char name2[MAXPATHLEN] ;
int apnd = 0 ;
int f0,f1 ;
FILE *rval ;
/* TODO: if absolute path, do we want to allow it?
* if relative path, do we want to prepend something?
*/
if( *name == '/' ) /* for now, disallow absolute paths */
return NULL ;
if( stat(name, &buf) == 0 )
exists = 1 ;
else if( errno == ENOENT )
exists = 0 ;
else
return NULL ;
/* if remote end has not specified transfer flags, we can
* accept the local definitions
*/
if( (f0=info->f0) == 0 ) {
if( ascii )
f0 = ZCNL ;
else if( binary )
f0 = ZCBIN ;
else if( resume )
f0 = ZCRESUM ;
else
f0 = 0 ;
}
if( (f1=info->f1) == 0 )
f1 = xferType | noloc ;
if( f0 == ZCRESUM ) { /* if exists, and we already have it, return */
if( exists && buf.st_size == info->len )
return NULL ;
apnd = 1 ;
}
/* reject if file not found and it most be there (ZMSKNOLOC) */
if( !exists && (f1 & ZMSKNOLOC) )
return NULL ;
switch( f1 & ZMMASK ) {
case 0: /* Implementation-dependent. In this case, we
* reject if file exists (and ZMSKNOLOC not set) */
if( exists && !(f1 & ZMSKNOLOC) ) {
fprintf(stderr, "%s already exists\n", name) ;
return NULL ;
}
break ;
case ZMNEWL: /* take if newer or longer than file on disk */
if( exists && info->date <= buf.st_mtime &&
info->len <= buf.st_size ) {
fprintf(stderr, "%s already exists\n", name) ;
return NULL ;
}
break ;
case ZMCRC: /* take if different CRC or length */
if( exists && info->len == buf.st_size && crc == FileCrc(name) )
{
fprintf(stderr, "%s already exists\n", name) ;
return NULL ;
}
break ;
case ZMAPND: /* append */
apnd = 1 ;
case ZMCLOB: /* unconditional replace */
break ;
case ZMNEW: /* take if newer than file on disk */
if( exists && info->date <= buf.st_mtime ) {
fprintf(stderr, "%s already exists and is newer\n", name) ;
return NULL ;
}
break ;
case ZMDIFF: /* take if different date or length */
if( exists && info->date == buf.st_mtime &&
info->len == buf.st_size )
{
fprintf(stderr, "%s already exists\n", name) ;
return NULL ;
}
break ;
case ZMPROT: /* only if dest does not exist */
if( exists )
{
fprintf(stderr, "%s already exists\n", name) ;
return NULL ;
}
break ;
case ZMCHNG: /* invent new filename if exists */
if( exists ) {
while( exists ) {
sprintf(name2, "%s_%d", name, changeCount++) ;
exists = stat(name2, &buf) == 0 || errno != ENOENT ;
}
name = name2 ;
}
break ;
}
/* here if we've decided to accept */
#ifdef COMMENT
if( exists && !apnd && unlink(name) != 0 )
return NULL ;
#endif /* COMMENT */
/* TODO: build directory path if needed */
if( verbose )
fprintf(stderr, "Receiving: \"%s\"\n", name) ;
rval = fopen(name, apnd ? "a" : "w") ;
if( rval == NULL )
perror(name) ;
return rval ;
}
int
ZWriteFile(u_char *buffer, int len, FILE *file, ZModem *info)
{
/* TODO: if ZCNL set in info->f0, convert
* newlines to local convention
*/
return fwrite(buffer, 1, len, file) == len ? 0 : ZmErrSys ;
}
int
ZCloseFile(ZModem *info)
{
struct timeval tvp[2] ;
fclose(info->file) ;
if( ymodem )
truncate(info->filename, info->len) ;
if( info->date != 0 ) {
tvp[0].tv_sec = tvp[1].tv_sec = info->date ;
tvp[0].tv_usec = tvp[1].tv_usec = 0 ;
utimes(info->filename, tvp) ;
}
if( info->mode & 01000000 )
chmod(info->filename, info->mode&0777) ;
return 0 ;
}
void
ZIdleStr(u_char *buffer, int len, ZModem *info)
{
#ifdef COMMENT
fwrite(buffer, 1,len, stdout) ;
#endif /* COMMENT */
}
void
ZFlowControl(int onoff, ZModem *info)
{
if( onoff ) {
new_settings.c_iflag |= IXON|IXANY|IXOFF ;
#ifdef COMMENT
new_settings.c_cflag |= CRTSCTS ;
#endif /* COMMENT */
}
else {
new_settings.c_iflag &= ~(IXON|IXANY|IXOFF) ;
new_settings.c_cflag &= ~CRTSCTS ;
}
tcsetattr(info->ifd,TCSADRAIN, &new_settings) ;
}
static char *
basename(char *name)
{
char *ptr ;
if( (ptr = strrchr(name, '/')) == NULL )
return name ;
else
return ++ptr ;
}

155
deps/Xmodem/network.c vendored Normal file
View File

@@ -0,0 +1,155 @@
#ifndef lint
static const char rcsid[] = "$Id: network.c,v 1.2 2001/10/25 23:56:29 efalk Exp $" ;
#endif
/*
* Copyright (c) 1995 by Edward A. Falk
*/
/**********
*
*
* @ @ @@@@@ @@@@@ @ @ @@@ @@@@ @ @
* @@ @ @ @ @ @ @ @ @ @ @ @
* @ @ @ @@@ @ @ @ @ @ @ @@@@ @@@
* @ @@ @ @ @ @ @ @ @ @ @ @ @
* @ @ @@@@@ @ @ @ @@@ @ @ @ @
*
* NETWORK - Make network connection
*
* Routines provided here:
*
*
* void
* IpConnect()
* Make IP connection according to parameters in gcomm.h
*
* void
* IpDisConnect()
* Close IP connection.
*
*
*
* Edward A. Falk
*
* January, 1995
*
*
*
**********/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <malloc.h>
#include <string.h>
#include <ctype.h>
#include <fcntl.h>
#include <varargs.h>
#include <errno.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/stat.h>
#ifdef COMMENT
#include <sys/ttold.h>
#include <sys/termio.h>
#endif /* COMMENT */
#include <termio.h>
#include <sys/stat.h>
#include <netdb.h> /* stuff used by tcp/ip */
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/wait.h>
#include <sys/signal.h>
#include "gcomm.h"
extern int errno ;
#ifdef COMMENT
extern char *sys_errlist[] ;
#endif /* COMMENT */
void
IpConnect()
{
int sockfd ;
int i,j ;
struct hostent *hostent ;
struct sockaddr_in sockaddr ;
int port ;
WindowStatus("Connecting...") ;
port = PortLookup(hostPort) ;
if( port == -1 )
return ;
bzero(&sockaddr, sizeof(sockaddr)) ;
sockaddr.sin_family = AF_INET ;
sockaddr.sin_port = htons(port) ;
hostent = gethostbyname(hostId) ;
if( hostent != NULL )
{
sockaddr.sin_addr = *(struct in_addr *) hostent->h_addr ;
}
else if( isdigit(hostId[0]) )
{
i = sscanf(hostId, "%d.%d.%d.%d",
&sockaddr.sin_addr.S_un.S_un_b.s_b1,
&sockaddr.sin_addr.S_un.S_un_b.s_b2,
&sockaddr.sin_addr.S_un.S_un_b.s_b3,
&sockaddr.sin_addr.S_un.S_un_b.s_b4) ;
if( i != 4 ) {
WindowStatus("Host address must be in dd.dd.dd.dd format") ;
return ;
}
}
else {
WindowStatus("Hostname not found") ;
return ;
}
sockfd = socket(AF_INET, SOCK_STREAM, 0) ;
if( sockfd < 0 ) {
WindowStatus("Cannot open socket: %s", sys_errlist[errno]) ;
return ;
}
i = connect(sockfd, &sockaddr, sizeof(sockaddr)) ;
if( i < 0 ) {
WindowStatus("Cannot connect to host: %s", sys_errlist[errno]) ;
close(sockfd) ;
return ;
}
ifd = ofd = sockfd ;
i = fcntl(ifd, F_GETFL, 0) ;
j = fcntl(ifd, F_SETFL, i|O_NDELAY) ;
connectionActive = 1 ;
connectTime0 = time(NULL) ;
WindowStatus("Connected") ;
}
void
IpDisConnect()
{
if( ifd == -1 )
return ;
close(ifd) ;
ifd = ofd = -1 ;
connectionActive = 0 ;
}

600
deps/Xmodem/receive.c vendored Normal file
View File

@@ -0,0 +1,600 @@
#ifndef lint
static const char rcsid[] = "$Id: receive.c,v 1.2 2001/10/25 23:56:29 efalk Exp $" ;
#endif
#define TEST /* standalone test */
#include <unistd.h>
#include <string.h>
#include "zmodem.h"
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/time.h>
#include <sys/termios.h>
#include <sys/termio.h> /* define TCSBRK */
#include <sys/param.h>
extern int errno ;
static u_char zeros[4] = {0,0,0,0} ;
main(argc,argv)
int argc ;
char **argv ;
{
struct termios old_settings, new_settings ;
fd_set readfds ;
struct timeval timeout ;
int i ;
int len ;
char buffer[1024] ;
int done = 0 ;
int filecount = 0 ;
ZModem info ;
#ifdef TEST
static u_char Amsg0[] = {
0x72, 0x7a, 0x0d, 0x2a, 0x2a, 0x18, 0x42, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x0d, 0x0a, 0x11,
} ;
static u_char Amsg1[] = {
0x2a, 0x18, 0x43, 0x02, 0x00, 0x00, 0x00, 0x00,
0x7d, 0xa4, 0xe2, 0xbc, 0x00, 0x18, 0x6b, 0x2f,
0xaa, 0xb9, 0x9b, 0x2a, 0x18, 0x43, 0x02, 0x00,
0x00, 0x00, 0x00, 0x7d, 0xa4, 0xe2, 0xbc,
} ;
static u_char Amsg2[] = {
0x00, 0x18, 0x6b, 0x2f, 0xaa, 0xb9, 0x9b, 0x2a,
0x18, 0x43, 0x04, 0x00, 0x00, 0x04, 0x00, 0xd9,
0x94, 0xce, 0x57,
} ;
static u_char Amsg3[] = {
0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x2e,
0x63, 0x00, 0x31, 0x36, 0x39, 0x38, 0x36, 0x20,
0x35, 0x37, 0x30, 0x30, 0x36, 0x36, 0x37, 0x36,
0x37, 0x30, 0x20, 0x31, 0x30, 0x30, 0x36, 0x36,
0x34, 0x20, 0x30, 0x20, 0x30, 0x20, 0x30, 0x20,
0x30, 0x00, 0x18, 0x6b, 0x57, 0xed, 0x76, 0xb6,
} ;
static u_char Amsg4[] = {
0x2a, 0x18, 0x43, 0x0a, 0x00, 0x00, 0x00, 0x00,
0xbc, 0xef, 0x92, 0x8c, 0x0a, 0x23, 0x64, 0x65,
0x66, 0x69, 0x6e, 0x65, 0x09, 0x54, 0x45, 0x53,
0x54, 0x09, 0x2f, 0x2a, 0x20, 0x73, 0x74, 0x61,
0x6e, 0x64, 0x61, 0x6c, 0x6f, 0x6e, 0x65, 0x20,
0x74, 0x65, 0x73, 0x74, 0x20, 0x2a, 0x2f, 0x0a,
0x0a, 0x23, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64,
0x65, 0x20, 0x3c, 0x75, 0x6e, 0x69, 0x73, 0x74,
0x64, 0x2e, 0x68, 0x3e, 0x0a, 0x23, 0x69, 0x6e,
0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x3c, 0x73,
0x74, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x68, 0x3e,
0x0a, 0x23, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64,
0x65, 0x20, 0x22, 0x7a, 0x6d, 0x6f, 0x64, 0x65,
0x6d, 0x2e, 0x68, 0x22, 0x0a, 0x23, 0x69, 0x6e,
0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x3c, 0x73,
0x79, 0x73, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x2e,
0x68, 0x3e, 0x0a, 0x0a, 0x23, 0x69, 0x6e, 0x63,
0x6c, 0x75, 0x64, 0x65, 0x20, 0x3c, 0x66, 0x63,
0x6e, 0x74, 0x6c, 0x2e, 0x68, 0x3e, 0x0a, 0x23,
0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20,
0x3c, 0x65, 0x72, 0x72, 0x6e, 0x6f, 0x2e, 0x68,
0x3e, 0x0a, 0x23, 0x69, 0x6e, 0x63, 0x6c, 0x75,
0x64, 0x65, 0x20, 0x3c, 0x73, 0x79, 0x73, 0x2f,
0x74, 0x69, 0x6d, 0x65, 0x2e, 0x68, 0x3e, 0x0a,
0x23, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65,
0x20, 0x3c, 0x73, 0x79, 0x73, 0x2f, 0x74, 0x65,
0x72, 0x6d, 0x69, 0x6f, 0x73, 0x2e, 0x68, 0x3e,
0x0a, 0x23, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64,
0x65, 0x20, 0x3c, 0x73, 0x79, 0x73, 0x2f, 0x74,
0x65, 0x72, 0x6d, 0x69, 0x6f, 0x2e, 0x68, 0x3e,
0x09, 0x09, 0x2f, 0x2a, 0x20, 0x64, 0x65, 0x66,
0x69, 0x6e, 0x65, 0x20, 0x54, 0x43, 0x53, 0x42,
0x52, 0x4b, 0x20, 0x2a, 0x2f, 0x0a, 0x23, 0x69,
0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x3c,
0x73, 0x79, 0x73, 0x2f, 0x70, 0x61, 0x72, 0x61,
0x6d, 0x2e, 0x68, 0x3e, 0x0a, 0x0a, 0x65, 0x78,
0x74, 0x65, 0x72, 0x6e, 0x09, 0x69, 0x6e, 0x74,
0x09, 0x65, 0x72, 0x72, 0x6e, 0x6f, 0x20, 0x3b,
0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63,
0x09, 0x75, 0x5f, 0x63, 0x68, 0x61, 0x72, 0x09,
0x7a, 0x65, 0x72, 0x6f, 0x73, 0x5b, 0x34, 0x5d,
0x20, 0x3d, 0x20, 0x7b, 0x30, 0x2c, 0x30, 0x2c,
0x30, 0x2c, 0x30, 0x7d, 0x20, 0x3b, 0x0a, 0x0a,
0x6d, 0x61, 0x69, 0x6e, 0x28, 0x61, 0x72, 0x67,
0x63, 0x2c, 0x61, 0x72, 0x67, 0x76, 0x29, 0x0a,
0x09, 0x69, 0x6e, 0x74, 0x09, 0x61, 0x72, 0x67,
0x63, 0x20, 0x3b, 0x0a, 0x09, 0x63, 0x68, 0x61,
0x72, 0x09, 0x2a, 0x2a, 0x61, 0x72, 0x67, 0x76,
0x20, 0x3b, 0x0a, 0x7b, 0x0a, 0x09, 0x73, 0x74,
0x72, 0x75, 0x63, 0x74, 0x09, 0x74, 0x65, 0x72,
0x6d, 0x69, 0x6f, 0x73, 0x09, 0x6f, 0x6c, 0x64,
0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67,
0x73, 0x2c, 0x20, 0x6e, 0x65, 0x77, 0x5f, 0x73,
0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20,
0x3b, 0x0a, 0x09, 0x66, 0x64, 0x5f, 0x73, 0x65,
0x74, 0x09, 0x72, 0x65, 0x61, 0x64, 0x66, 0x64,
0x73, 0x20, 0x3b, 0x0a, 0x09, 0x73, 0x74, 0x72,
0x75, 0x63, 0x74, 0x20, 0x74, 0x69, 0x6d, 0x65,
0x76, 0x61, 0x6c, 0x20, 0x74, 0x69, 0x6d, 0x65,
0x6f, 0x75, 0x74, 0x20, 0x3b, 0x0a, 0x09, 0x69,
0x6e, 0x74, 0x09, 0x69, 0x20, 0x3b, 0x0a, 0x09,
0x69, 0x6e, 0x74, 0x09, 0x6c, 0x65, 0x6e, 0x20,
0x3b, 0x0a, 0x09, 0x63, 0x68, 0x61, 0x72, 0x09,
0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5b, 0x31,
0x30, 0x32, 0x34, 0x5d, 0x20, 0x3b, 0x0a, 0x09,
0x69, 0x6e, 0x74, 0x09, 0x64, 0x6f, 0x6e, 0x65,
0x20, 0x3d, 0x20, 0x30, 0x20, 0x3b, 0x0a, 0x09,
0x69, 0x6e, 0x74, 0x09, 0x66, 0x69, 0x6c, 0x65,
0x63, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x3d, 0x20,
0x30, 0x20, 0x3b, 0x0a, 0x09, 0x5a, 0x4d, 0x6f,
0x64, 0x65, 0x6d, 0x09, 0x69, 0x6e, 0x66, 0x6f,
0x20, 0x3b, 0x0a, 0x0a, 0x23, 0x69, 0x66, 0x64,
0x65, 0x66, 0x09, 0x54, 0x45, 0x53, 0x54, 0x0a,
0x0a, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x09,
0x75, 0x5f, 0x63, 0x68, 0x61, 0x72, 0x09, 0x41,
0x6d, 0x73, 0x67, 0x30, 0x5b, 0x5d, 0x20, 0x3d,
0x20, 0x7b, 0x0a, 0x09, 0x20, 0x20, 0x30, 0x78,
0x37, 0x32, 0x2c, 0x20, 0x30, 0x78, 0x37, 0x61,
0x2c, 0x20, 0x30, 0x78, 0x30, 0x64, 0x2c, 0x20,
0x30, 0x78, 0x32, 0x61, 0x2c, 0x20, 0x30, 0x78,
0x32, 0x61, 0x2c, 0x20, 0x30, 0x78, 0x31, 0x38,
0x2c, 0x20, 0x30, 0x78, 0x34, 0x32, 0x2c, 0x20,
0x30, 0x78, 0x33, 0x30, 0x2c, 0x20, 0x0a, 0x09,
0x20, 0x20, 0x30, 0x78, 0x33, 0x30, 0x2c, 0x20,
0x30, 0x78, 0x33, 0x30, 0x2c, 0x20, 0x30, 0x78,
0x33, 0x30, 0x2c, 0x20, 0x30, 0x78, 0x33, 0x30,
0x2c, 0x20, 0x30, 0x78, 0x33, 0x30, 0x2c, 0x20,
0x30, 0x78, 0x33, 0x30, 0x2c, 0x20, 0x30, 0x78,
0x33, 0x30, 0x2c, 0x20, 0x30, 0x78, 0x33, 0x30,
0x2c, 0x20, 0x0a, 0x09, 0x20, 0x20, 0x30, 0x78,
0x33, 0x30, 0x2c, 0x20, 0x30, 0x78, 0x33, 0x30,
0x2c, 0x20, 0x30, 0x78, 0x33, 0x30, 0x2c, 0x20,
0x30, 0x78, 0x33, 0x30, 0x2c, 0x20, 0x30, 0x78,
0x33, 0x30, 0x2c, 0x20, 0x30, 0x78, 0x30, 0x64,
0x2c, 0x20, 0x30, 0x78, 0x30, 0x61, 0x2c, 0x20,
0x30, 0x78, 0x31, 0x31, 0x2c, 0x20, 0x0a, 0x09,
0x7d, 0x20, 0x3b, 0x0a, 0x73, 0x74, 0x61, 0x74,
0x69, 0x63, 0x09, 0x75, 0x5f, 0x63, 0x68, 0x61,
0x72, 0x09, 0x41, 0x6d, 0x73, 0x67, 0x31, 0x5b,
0x5d, 0x20, 0x3d, 0x20, 0x7b, 0x0a, 0x09, 0x20,
0x20, 0x30, 0x78, 0x32, 0x61, 0x2c, 0x20, 0x30,
0x78, 0x31, 0x38, 0x2c, 0x20, 0x30, 0x78, 0x34,
0x33, 0x2c, 0x20, 0x30, 0x78, 0x30, 0x34, 0x2c,
0x20, 0x30, 0x78, 0x30, 0x30, 0x2c, 0x20, 0x30,
0x78, 0x30, 0x30, 0x2c, 0x20, 0x30, 0x78, 0x30,
0x30, 0x2c, 0x20, 0x30, 0x78, 0x30, 0x30, 0x2c,
0x20, 0x0a, 0x09, 0x20, 0x20, 0x30, 0x78, 0x64,
0x64, 0x2c, 0x20, 0x30, 0x78, 0x35, 0x31, 0x2c,
0x20, 0x30, 0x78, 0x61, 0x32, 0x2c, 0x20, 0x30,
0x78, 0x33, 0x33, 0x2c, 0x20, 0x30, 0x78, 0x37,
0x35, 0x2c, 0x20, 0x30, 0x78, 0x37, 0x34, 0x2c,
0x20, 0x30, 0x78, 0x36, 0x39, 0x2c, 0x20, 0x30,
0x78, 0x36, 0x63, 0x2c, 0x20, 0x0a, 0x09, 0x20,
0x20, 0x30, 0x78, 0x37, 0x33, 0x2c, 0x20, 0x30,
0x78, 0x32, 0x65, 0x2c, 0x20, 0x30, 0x78, 0x36,
0x33, 0x2c, 0x20, 0x30, 0x78, 0x30, 0x30, 0x2c,
0x20, 0x30, 0x78, 0x33, 0x31, 0x2c, 0x20, 0x30,
0x78, 0x33, 0x31, 0x2c, 0x20, 0x30, 0x78, 0x33,
0x30, 0x2c, 0x20, 0x30, 0x78, 0x33, 0x37, 0x2c,
0x20, 0x0a, 0x09, 0x20, 0x20, 0x30, 0x78, 0x32,
0x30, 0x2c, 0x20, 0x30, 0x78, 0x33, 0x35, 0x2c,
0x20, 0x30, 0x78, 0x33, 0x37, 0x2c, 0x20, 0x30,
0x78, 0x33, 0x30, 0x2c, 0x20, 0x30, 0x78, 0x33,
0x30, 0x2c, 0x20, 0x30, 0x78, 0x33, 0x30, 0x2c,
0x20, 0x30, 0x78, 0x33, 0x35, 0x2c, 0x20, 0x30,
0x78, 0x33, 0x36, 0x2c, 0x20, 0x0a, 0x09, 0x20,
0x20, 0x30, 0x78, 0x33, 0x31, 0x2c, 0x20, 0x30,
0x78, 0x33, 0x30, 0x2c, 0x20, 0x30, 0x78, 0x33,
0x34, 0x2c, 0x20, 0x30, 0x78, 0x32, 0x30, 0x2c,
0x20, 0x30, 0x78, 0x33, 0x18, 0x6a, 0xf8, 0x0e,
0xd1, 0x2f, 0x31, 0x2c, 0x20, 0x30, 0x78, 0x33,
0x30, 0x2c, 0x20, 0x30, 0x78, 0x33, 0x30, 0x2c,
0x20, 0x30, 0x78, 0x33, 0x36, 0x2c, 0x20, 0x0a,
0x09, 0x20, 0x20, 0x30, 0x78, 0x33, 0x36, 0x2c,
0x20, 0x30, 0x78, 0x33, 0x34, 0x2c, 0x20, 0x30,
0x78, 0x32, 0x30, 0x2c, 0x20, 0x30, 0x78, 0x33,
0x30, 0x2c, 0x20, 0x30, 0x78, 0x32, 0x30, 0x2c,
0x20, 0x30, 0x78, 0x33, 0x30, 0x2c, 0x20, 0x30,
0x78, 0x32, 0x30, 0x2c, 0x20, 0x30, 0x78, 0x33,
0x30, 0x2c, 0x20, 0x0a, 0x09, 0x20, 0x20, 0x30,
0x78, 0x32, 0x30, 0x2c, 0x20, 0x30, 0x78, 0x33,
0x30, 0x2c, 0x20, 0x30, 0x78, 0x30, 0x30, 0x2c,
0x20, 0x30, 0x78, 0x31, 0x38, 0x2c, 0x20, 0x30,
0x78, 0x36, 0x62, 0x2c, 0x20, 0x30, 0x78, 0x63,
0x63, 0x2c, 0x20, 0x30, 0x78, 0x38, 0x38, 0x2c,
0x20, 0x30, 0x78, 0x38, 0x36, 0x2c, 0x20, 0x0a,
0x09, 0x20, 0x20, 0x30, 0x78, 0x31, 0x61, 0x2c,
0x20, 0x0a, 0x09, 0x7d, 0x20, 0x3b, 0x0a, 0x73,
0x74, 0x61, 0x74, 0x69, 0x63, 0x09, 0x75, 0x5f,
0x63, 0x68, 0x61, 0x72, 0x09, 0x41, 0x6d, 0x73,
0x67, 0x32, 0x5b, 0x5d, 0x20, 0x3d, 0x20, 0x7b,
0x0a, 0x09, 0x20, 0x20, 0x30, 0x78, 0x32, 0x61,
0x2c, 0x20, 0x30, 0x78, 0x31, 0x38, 0x2c, 0x20,
0x30, 0x78, 0x34, 0x33, 0x2c, 0x20, 0x30, 0x78,
0x30, 0x34, 0x2c, 0x20, 0x30, 0x78, 0x30, 0x30,
0x2c, 0x20, 0x30, 0x78, 0x30, 0x30, 0x2c, 0x20,
0x30, 0x78, 0x30, 0x30, 0x2c, 0x20, 0x30, 0x78,
0x30, 0x30, 0x2c, 0x20, 0x0a, 0x09, 0x20, 0x20,
0x30, 0x78, 0x64, 0x64, 0x2c, 0x20, 0x30, 0x78,
0x35, 0x31, 0x2c, 0x20, 0x30, 0x78, 0x61, 0x32,
0x2c, 0x20, 0x30, 0x78, 0x33, 0x33, 0x2c, 0x20,
0x30, 0x78, 0x37, 0x35, 0x2c, 0x20, 0x30, 0x78,
0x37, 0x34, 0x2c, 0x20, 0x30, 0x78, 0x36, 0x39,
0x2c, 0x20, 0x30, 0x78, 0x36, 0x63, 0x2c, 0x20,
0x0a, 0x09, 0x20, 0x20, 0x30, 0x78, 0x37, 0x33,
0x2c, 0x20, 0x30, 0x78, 0x32, 0x65, 0x2c, 0x20,
0x30, 0x78, 0x36, 0x33, 0x2c, 0x20, 0x30, 0x78,
0x30, 0x30, 0x2c, 0x20, 0x30, 0x78, 0x33, 0x31,
0x2c, 0x20, 0x30, 0x78, 0x33, 0x31, 0x2c, 0x20,
0x30, 0x78, 0x33, 0x30, 0x2c, 0x20, 0x30, 0x78,
0x33, 0x37, 0x2c, 0x20, 0x0a, 0x09, 0x20, 0x20,
0x30, 0x78, 0x32, 0x30, 0x2c, 0x20, 0x30, 0x78,
0x33, 0x35, 0x2c, 0x20, 0x30, 0x78, 0x33, 0x37,
0x2c, 0x20, 0x30, 0x78, 0x33, 0x30, 0x2c, 0x20,
0x30, 0x78, 0x33, 0x30, 0x2c, 0x20, 0x30, 0x78,
0x33, 0x30, 0x2c, 0x20, 0x30, 0x78, 0x33, 0x35,
0x2c, 0x20, 0x30, 0x78, 0x33, 0x36, 0x2c, 0x20,
0x0a, 0x09, 0x20, 0x20, 0x30, 0x78, 0x33, 0x31,
0x2c, 0x20, 0x30, 0x78, 0x33, 0x30, 0x2c, 0x20,
0x30, 0x78, 0x33, 0x34, 0x2c, 0x20, 0x30, 0x78,
0x32, 0x30, 0x2c, 0x20, 0x30, 0x78, 0x33, 0x31,
0x2c, 0x20, 0x30, 0x78, 0x33, 0x30, 0x2c, 0x20,
0x30, 0x78, 0x33, 0x30, 0x2c, 0x20, 0x30, 0x78,
0x33, 0x36, 0x2c, 0x20, 0x0a, 0x09, 0x20, 0x20,
0x30, 0x78, 0x33, 0x36, 0x2c, 0x20, 0x30, 0x78,
0x33, 0x34, 0x2c, 0x20, 0x30, 0x78, 0x32, 0x30,
0x2c, 0x20, 0x30, 0x78, 0x33, 0x30, 0x2c, 0x20,
0x30, 0x78, 0x32, 0x30, 0x2c, 0x20, 0x30, 0x78,
0x33, 0x30, 0x2c, 0x20, 0x30, 0x78, 0x32, 0x30,
0x2c, 0x20, 0x30, 0x78, 0x33, 0x30, 0x2c, 0x20,
0x0a, 0x09, 0x20, 0x20, 0x30, 0x78, 0x32, 0x30,
0x2c, 0x20, 0x30, 0x78, 0x33, 0x30, 0x2c, 0x20,
0x30, 0x78, 0x30, 0x30, 0x2c, 0x20, 0x30, 0x78,
0x31, 0x38, 0x2c, 0x20, 0x30, 0x78, 0x36, 0x62,
0x2c, 0x20, 0x30, 0x78, 0x63, 0x63, 0x2c, 0x20,
0x30, 0x78, 0x38, 0x38, 0x2c, 0x20, 0x30, 0x78,
0x38, 0x36, 0x2c, 0x20, 0x0a, 0x09, 0x20, 0x20,
0x30, 0x78, 0x31, 0x61, 0x2c, 0x20, 0x0a, 0x09,
0x7d, 0x20, 0x3b, 0x0a, 0x73, 0x74, 0x61, 0x74,
0x69, 0x63, 0x09, 0x75, 0x5f, 0x63, 0x68, 0x61,
0x72, 0x09, 0x41, 0x6d, 0x73, 0x67, 0x33, 0x5b,
0x5d, 0x20, 0x3d, 0x20, 0x7b, 0x0a, 0x09, 0x20,
0x20, 0x30, 0x78, 0x32, 0x61, 0x2c, 0x20, 0x30,
0x78, 0x31, 0x38, 0x2c, 0x20, 0x30, 0x78, 0x34,
0x33, 0x2c, 0x20, 0x30, 0x78, 0x30, 0x61, 0x2c,
0x20, 0x30, 0x78, 0x30, 0x30, 0x2c, 0x20, 0x30,
0x78, 0x30, 0x30, 0x2c, 0x20, 0x30, 0x78, 0x30,
0x30, 0x2c, 0x20, 0x30, 0x78, 0x30, 0x30, 0x2c,
0x20, 0x0a, 0x09, 0x20, 0x20, 0x30, 0x78, 0x62,
0x63, 0x2c, 0x20, 0x30, 0x78, 0x65, 0x66, 0x2c,
0x20, 0x30, 0x78, 0x39, 0x32, 0x2c, 0x20, 0x30,
0x78, 0x38, 0x63, 0x2c, 0x20, 0x30, 0x78, 0x30,
0x61, 0x2c, 0x20, 0x30, 0x78, 0x32, 0x33, 0x2c,
0x20, 0x30, 0x78, 0x36, 0x39, 0x2c, 0x20, 0x30,
0x78, 0x36, 0x65, 0x2c, 0x20, 0x0a, 0x09, 0x20,
0x20, 0x30, 0x78, 0x36, 0x33, 0x2c, 0x20, 0x30,
0x78, 0x36, 0x63, 0x2c, 0x20, 0x30, 0x78, 0x37,
0x35, 0x2c, 0x20, 0x30, 0x78, 0x36, 0x34, 0x2c,
0x20, 0x30, 0x78, 0x36, 0x35, 0x2c, 0x20, 0x30,
0x78, 0x32, 0x30, 0x2c, 0x20, 0x30, 0x78, 0x33,
0x63, 0x2c, 0x20, 0x30, 0x78, 0x37, 0x33, 0x2c,
0x20, 0x0a, 0x09, 0x20, 0x20, 0x30, 0x78, 0x37,
0x39, 0x2c, 0x20, 0x30, 0x78, 0x36, 0x33, 0x2c,
0x20, 0x30, 0x78, 0x32, 0x66, 0x2c, 0x20, 0x30,
0x78, 0x37, 0x34, 0x2c, 0x20, 0x30, 0x78, 0x36,
0x35, 0x2c, 0x20, 0x30, 0x78, 0x37, 0x32, 0x2c,
0x20, 0x30, 0x78, 0x36, 0x64, 0x2c, 0x20, 0x30,
0x78, 0x36, 0x39, 0x2c, 0x20, 0x0a, 0x09, 0x20,
0x20, 0x30, 0x78, 0x36, 0x66, 0x2c, 0x20, 0x30,
0x78, 0x37, 0x33, 0x2c, 0x20, 0x30, 0x78, 0x32,
0x65, 0x2c, 0x20, 0x30, 0x78, 0x36, 0x38, 0x2c,
0x20, 0x30, 0x78, 0x33, 0x65, 0x2c, 0x20, 0x30,
0x78, 0x30, 0x61, 0x2c, 0x20, 0x30, 0x78, 0x32,
0x33, 0x2c, 0x20, 0x30, 0x78, 0x36, 0x39, 0x2c,
0x20, 0x0a, 0x09, 0x20, 0x20, 0x30, 0x78, 0x36,
0x65, 0x2c, 0x20, 0x30, 0x78, 0x36, 0x33, 0x2c,
0x20, 0x30, 0x78, 0x36, 0x63, 0x2c, 0x20, 0x30,
0x78, 0x37, 0x35, 0x2c, 0x20, 0x30, 0x78, 0x36,
0x34, 0x2c, 0x20, 0x30, 0x78, 0x36, 0x35, 0x2c,
0x20, 0x30, 0x78, 0x32, 0x30, 0x2c, 0x20, 0x30,
0x78, 0x32, 0x32, 0x2c, 0x20, 0x0a, 0x09, 0x20,
0x20, 0x30, 0x78, 0x37, 0x38, 0x2c, 0x20, 0x30,
0x78, 0x36, 0x64, 0x2c, 0x20, 0x30, 0x78, 0x36,
0x66, 0x2c, 0x20, 0x30, 0x78, 0x36, 0x34, 0x2c,
0x20, 0x30, 0x78, 0x36, 0x35, 0x2c, 0x20, 0x30,
0x78, 0x36, 0x64, 0x2c, 0x20, 0x30, 0x78, 0x32,
0x65, 0x2c, 0x20, 0x30, 0x78, 0x36, 0x38, 0x2c,
0x20, 0x0a, 0x09, 0x20, 0x20, 0x30, 0x78, 0x32,
0x32, 0x2c, 0x20, 0x30, 0x78, 0x30, 0x61, 0x2c,
0x20, 0x30, 0x78, 0x30, 0x61, 0x2c, 0x20, 0x30,
0x78, 0x30, 0x61, 0x2c, 0x20, 0x30, 0x78, 0x36,
0x39, 0x2c, 0x20, 0x30, 0x78, 0x36, 0x65, 0x2c,
0x20, 0x30, 0x78, 0x37, 0x34, 0x2c, 0x20, 0x30,
0x78, 0x30, 0x61, 0x2c, 0x20, 0x0a, 0x09, 0x20,
0x20, 0x30, 0x78, 0x37, 0x33, 0x2c, 0x20, 0x30,
0x78, 0x36, 0x35, 0x2c, 0x20, 0x30, 0x78, 0x36,
0x65, 0x2c, 0x20, 0x30, 0x78, 0x36, 0x34, 0x2c,
0x20, 0x30, 0x78, 0x34, 0x33, 0x2c, 0x20, 0x30,
0x78, 0x36, 0x18, 0x6a, 0x4a, 0xe5, 0x72, 0x71,
} ;
#define E(b) {b, sizeof(b)}
static struct {u_char *am; int len} Amsgs[] = {
E(Amsg0),
E(Amsg1),
E(Amsg2),
E(Amsg3),
E(Amsg4),} ;
#endif /* TEST */
/* try to trap uninit. variables */
memset(&info,0xa5,sizeof(info)) ;
info.zrinitflags = CANFDX|CANOVIO|CANBRK|CANFC32 ;
info.packetsize = 128 ;
info.bufsize = 0 ;
#ifdef TEST
done = ZmodemRInit(&info) ;
for(i=0; !done; ++i )
done = ZmodemRcv(Amsgs[i].am, Amsgs[i].len, &info) ;
#else
if( argc < 2 )
exit(2) ;
info.ifd = open(argv[1], O_RDWR) ;
if( info.ifd == -1 )
exit(1) ;
tcgetattr(info.ifd,&old_settings) ;
new_settings = old_settings ;
new_settings.c_iflag &=
~(ISTRIP|INLCR|IGNCR|ICRNL|IUCLC|IXON|IXOFF|IMAXBEL) ;
new_settings.c_oflag = 0 ;
new_settings.c_cflag = B300|CS8|CREAD|CLOCAL ;
new_settings.c_lflag = 0 ;
new_settings.c_cc[VMIN] = 32 ;
new_settings.c_cc[VTIME] = 1 ;
tcsetattr(info.ifd,TCSADRAIN, &new_settings) ;
done = ZmodemRInit(&info) ;
while(!done)
{
FD_ZERO(&readfds) ;
FD_SET(info.ifd, &readfds) ;
timeout.tv_sec = info.timeout ;
timeout.tv_usec = 0 ;
i = select(info.ifd+1, &readfds,NULL,NULL, &timeout) ;
if( i<0 )
perror("select") ;
else if( i==0 )
done = ZmodemTimeout(&info) ;
else {
len = read(info.ifd, buffer, sizeof(buffer)) ;
done = ZmodemRcv(buffer, len, &info) ;
}
}
tcsetattr(info.ifd,TCSADRAIN, &old_settings) ;
#endif /* TEST */
exit(0) ;
}
int
ZXmitStr(buffer, len, info)
u_char *buffer ;
int len ;
ZModem *info ;
{
int i,j ;
u_char c ;
extern double drand48() ;
#ifdef TEST
for(i=0; i<len; i += 16)
{
printf(" ") ;
for(j=0; j<16 && i+j<len; ++j)
printf("%2.2x ", buffer[i+j]) ;
for(; j<16; ++j)
printf(" ") ;
printf(" |") ;
for(j=0; j<16 && i+j<len; ++j)
putchar(((c=buffer[i+j]) < 040 || c >= 0177) ? '.' : c ) ;
printf("|\n") ;
}
#else
#ifdef COMMENT
/* TEST: randomly corrupt one out of every 300 bytes */
for(i=0; i<len; ++i)
if( drand48() < 1./300. ) {
fprintf(stderr, "byte %d was %2.2x, is", i, buffer[i]) ;
buffer[i] ^= 1<<(lrand48()&7) ;
fprintf(stderr, " %2.2x\n", buffer[i]) ;
}
#endif /* COMMENT */
if( write(info->ifd, buffer, len) != len )
return ZmErrSys ;
#endif /* TEST */
return 0 ;
}
void
ZIFlush(info)
ZModem *info ;
{
}
void
ZOFlush(info)
ZModem *info ;
{
}
void
ZStatus(i,j,str)
{
fprintf(stderr,"status %d=%d\n",i,j) ;
}
int
ZAttn(info)
ZModem *info ;
{
char *ptr ;
int i = 0 ;
for(ptr = info->attn; *ptr != '\0'; ++ptr) {
if( *ptr == ATTNBRK )
ioctl(info->ifd, TCSBRK, 0) ;
else if( *ptr == ATTNPSE )
sleep(1) ;
else
write(info->ifd, ptr, 1) ;
}
return 0 ;
}
FILE *
ZOpenFile(name, crc, info)
char *name ;
u_long crc ;
ZModem *info ;
{
struct stat buf ;
int exists ; /* file already exists */
static int changeCount = 0 ;
char name2[MAXPATHLEN] ;
int apnd = 0 ;
int f0,f1,f2,f3 ;
/* TODO: if absolute path, do we want to allow it?
* if relative path, do we want to prepend something?
*/
if( *name == '/' ) /* for now, disallow absolute paths */
return NULL ;
if( stat(name, &buf) == 0 )
exists = 1 ;
else if( errno == ENOENT )
exists = 0 ;
else
return NULL ;
/* if remote end has not specified transfer flags, we can
* accept the local definitions
*/
if( f0 == ZCRESUM ) { /* if exists, and we already have it, return */
if( exists && buf.st_size == info->len )
return NULL ;
apnd = 1 ;
}
/* reject if file not found and it most be there (ZMSKNOLOC) */
if( !exists && (f1 & ZMSKNOLOC) )
return NULL ;
switch( f1 & ZMMASK ) {
case 0: /* Implementation-dependent. In this case, we
* reject if file exists (and ZMSKNOLOC not set) */
if( exists && !(f1 & ZMSKNOLOC) )
return NULL ;
break ;
case ZMNEWL: /* take if newer or longer than file on disk */
if( exists && info->date <= buf.st_mtime &&
info->len <= buf.st_size )
return NULL ;
break ;
case ZMCRC: /* take if different CRC or length */
if( exists && info->len == buf.st_size && crc == FileCrc(name) )
return NULL ;
break ;
case ZMAPND: /* append */
apnd = 1 ;
case ZMCLOB: /* unconditional replace */
break ;
case ZMNEW: /* take if newer than file on disk */
if( exists && info->date <= buf.st_mtime )
return NULL ;
break ;
case ZMDIFF: /* take if different date or length */
if( exists && info->date == buf.st_mtime &&
info->len == buf.st_size )
return NULL ;
break ;
case ZMPROT: /* only if dest does not exist */
if( exists )
return NULL ;
break ;
case ZMCHNG: /* invent new filename if exists */
if( exists ) {
while( exists ) {
sprintf(name2, "%s_%d", name, changeCount++) ;
exists = stat(name2, &buf) == 0 || errno != ENOENT ;
}
name = name2 ;
}
break ;
}
/* here if we've decided to accept */
if( exists && !apnd && unlink(name) != 0 )
return NULL ;
/* TODO: build directory path if needed */
return fopen(name, apnd ? "a" : "w") ;
}
int
ZWriteFile(buffer, len, file, info)
u_char *buffer ;
int len ;
FILE *file ;
ZModem *info ;
{
/* TODO: if ZCNL set in info->f0, convert
* newlines to local convention
*/
return fwrite(buffer, 1, len, file) == len ? 0 : ZmErrSys ;
}
int
ZCloseFile(info)
ZModem *info ;
{
fclose(info->file) ;
chmod(info->filename, info->mode&0777) ;
}

327
deps/Xmodem/send.c vendored Normal file
View File

@@ -0,0 +1,327 @@
#ifndef lint
static const char rcsid[] = "$Id: send.c,v 1.2 2001/10/25 23:56:29 efalk Exp $" ;
#endif
#define TEST /* standalone test */
#include <unistd.h>
#include <string.h>
#include "zmodem.h"
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/time.h>
#include <sys/termios.h>
#include <sys/termio.h> /* define TCSBRK */
#include <sys/param.h>
extern int errno ;
static u_char zeros[4] = {0,0,0,0} ;
main(argc,argv)
int argc ;
char **argv ;
{
struct termios old_settings, new_settings ;
fd_set readfds ;
struct timeval timeout ;
int i ;
int len ;
char buffer[1024] ;
int done = 0 ;
int filecount = 0 ;
ZModem info ;
#ifdef TEST
static u_char Amsg0[] = {
0x43,
} ;
static u_char Amsg1[] = {
0x06, 0x43,
} ;
static u_char Amsg2[] = {
0x06,
} ;
static u_char Amsg3[] = {
0x06,
} ;
static u_char Amsg4[] = {
0x06, 0x43,
} ;
static u_char Amsg5[] = {
0x06, 0x43,
} ;
static u_char Amsg6[] = {
0x06,
} ;
static u_char Amsg7[] = {
0x06,
} ;
static u_char Amsg8[] = {
0x06,
} ;
static u_char Amsg9[] = {
0x06, 0x43,
} ;
#define E(b) {b, sizeof(b)}
static struct {u_char *bm; int len} Bmsgs[] = {
E(Amsg0),
E(Amsg1),
E(Amsg2),
E(Amsg3),
E(Amsg4),
E(Amsg5),
E(Amsg6),
E(Amsg7),
E(Amsg8),
E(Amsg9),} ;
#endif /* TEST */
/* try to trap uninit. variables */
memset(&info,0xa5,sizeof(info)) ;
info.zsinitflags = 0 ;
info.attn = "\17\336" ;
info.packetsize = 1024 ;
info.windowsize = 4096 ;
#ifdef TEST
done = YmodemTInit(&info) ;
for(i=0; !done; ++i )
done = ZmodemRcv(Bmsgs[i].bm, Bmsgs[i].len, &info) ;
done = ZmodemTFile("utils.c","utils.c", 0,0,0,0, 1,0, &info) ;
for(; !done; ++i )
done = ZmodemRcv(Bmsgs[i].bm, Bmsgs[i].len, &info) ;
done = ZmodemTFile("foo.c","foo.c", 0,0,0,0, 1,0, &info) ;
for(; !done; ++i )
done = ZmodemRcv(Bmsgs[i].bm, Bmsgs[i].len, &info) ;
done = ZmodemTFinish(info) ;
#else
if( argc < 2 )
exit(2) ;
info.ifd = open(argv[1], O_RDWR) ;
if( info.ifd == -1 )
exit(1) ;
tcgetattr(info.ifd,&old_settings) ;
new_settings = old_settings ;
new_settings.c_iflag &=
~(ISTRIP|INLCR|IGNCR|ICRNL|IUCLC|IXON|IXOFF|IMAXBEL) ;
new_settings.c_oflag = 0 ;
new_settings.c_cflag = B300|CS8|CREAD|CLOCAL ;
new_settings.c_lflag = 0 ;
new_settings.c_cc[VMIN] = 32 ;
new_settings.c_cc[VTIME] = 1 ;
tcsetattr(info.ifd,TCSADRAIN, &new_settings) ;
InitXmit(&info) ;
XmitFile("utils.c",1,0,&info) ;
#ifdef COMMENT
XmitFile("foo",1,0,&info) ;
XmitFile("foo.c",1,0,&info) ;
XmitFile("raw",1,0,&info) ;
#endif /* COMMENT */
FinishXmit(&info) ;
tcsetattr(info.ifd,TCSADRAIN, &old_settings) ;
#endif /* TEST */
exit(0) ;
}
static int
doIO(info)
ZModem *info ;
{
fd_set readfds ;
struct timeval timeout ;
int i ;
int len ;
char buffer[1024] ;
int done = 0 ;
while(!done)
{
FD_ZERO(&readfds) ;
FD_SET(info->ifd, &readfds) ;
timeout.tv_sec = info->timeout ;
timeout.tv_usec = 0 ;
i = select(info->ifd+1, &readfds,NULL,NULL, &timeout) ;
if( i<0 )
perror("select") ;
else if( i==0 )
done = ZmodemTimeout(info) ;
else {
len = read(info->ifd, buffer, sizeof(buffer)) ;
done = ZmodemRcv(buffer, len, info) ;
}
}
return done ;
}
int
InitXmit(info)
ZModem *info ;
{
int done ;
done = ZmodemTInit(info) ;
if( !done )
done = doIO(info) ;
return done != ZmDone ;
}
XmitFile(filename,nfiles,nbytes,info)
char *filename ;
int nfiles, nbytes ;
ZModem *info ;
{
int done ;
done = ZmodemTFile(filename,filename, 0,ZMCLOB,0,0,
nfiles,nbytes, info) ;
if( done == ZmErrCantOpen || done == ZmFileTooLong )
return 0 ;
if( !done )
done = doIO(info) ;
return done != ZmDone ;
}
FinishXmit(info)
ZModem *info ;
{
int done ;
done = ZmodemTFinish(info) ;
if( !done )
done = doIO(info) ;
return done != ZmDone ;
}
int
ZXmitStr(buffer, len, info)
u_char *buffer ;
int len ;
ZModem *info ;
{
int i,j ;
u_char c ;
extern double drand48() ;
#ifdef TEST
for(i=0; i<len; i += 16)
{
printf(" ") ;
for(j=0; j<16 && i+j<len; ++j)
printf("%2.2x ", buffer[i+j]) ;
for(; j<16; ++j)
printf(" ") ;
printf(" |") ;
for(j=0; j<16 && i+j<len; ++j)
putchar(((c=buffer[i+j]) < 040 || c >= 0177) ? '.' : c ) ;
printf("|\n") ;
}
#else
#ifdef COMMENT
/* TEST: randomly corrupt one out of every 300 bytes */
for(i=0; i<len; ++i)
if( drand48() < 1./300. ) {
fprintf(stderr, "byte %d was %2.2x, is", i, buffer[i]) ;
buffer[i] ^= 1<<(lrand48()&7) ;
fprintf(stderr, " %2.2x\n", buffer[i]) ;
}
#endif /* COMMENT */
if( write(info->ifd, buffer, len) != len )
return ZmErrSys ;
#endif /* TEST */
return 0 ;
}
void
ZIFlush(info)
ZModem *info ;
{
}
void
ZOFlush(info)
ZModem *info ;
{
}
void
ZStatus(i,j,str)
{
fprintf(stderr,"status %d=%d\n",i,j) ;
}
int
ZAttn(info)
ZModem *info ;
{
char *ptr ;
int i = 0 ;
for(ptr = info->attn; *ptr != '\0'; ++ptr) {
if( *ptr == ATTNBRK )
ioctl(info->ifd, TCSBRK, 0) ;
else if( *ptr == ATTNPSE )
sleep(1) ;
else
write(info->ifd, ptr, 1) ;
}
return 0 ;
}
FILE *
ZOpenFile(name, f0,f1,f2,f3, len, date, mode, filesRem, bytesRem, crc)
char *name ;
int f0,f1,f2,f3, len, mode, filesRem, bytesRem ;
long date ;
u_long crc ;
{
}
int
ZWriteFile()
{}
ZCloseFile(info)
ZModem *info ;
{}
ZFlowControl(info)
ZModem *info ;
{}

86
deps/Xmodem/seriallog.c vendored Normal file
View File

@@ -0,0 +1,86 @@
#ifndef lint
static const char rcsid[] = "$Id: seriallog.c,v 1.2 2001/10/25 23:56:29 efalk Exp $" ;
#endif
/* seriallog routines. Write data to log file, tagged with timestamp
* and channel.
*/
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <sys/time.h>
#include "seriallog.h"
static struct timeval timestamp = {0,0} ;
#define DTIME 1500 /* timeout, milliseconds */
static int which = -1 ; /* last transmitted */
static char obuf[4096] ;
static int olen = -1 ;
FILE *SerialLogFile = NULL ;
/* flush out buffered text */
void
SerialLogFlush()
{
int i ;
if( SerialLogFile == NULL )
return ;
if( which != -1 && olen > 0 )
{
i = fwrite((char *)&which, sizeof(int), 1, SerialLogFile) ;
i = fwrite((char *)&timestamp, sizeof(timestamp), 1, SerialLogFile) ;
i = fwrite((char *)&olen, sizeof(int), 1, SerialLogFile) ;
i = fwrite(obuf, 1, olen, SerialLogFile) ;
}
fflush(SerialLogFile) ;
which = -1 ;
olen = 0 ;
}
void
SerialLog(const void *data, int len, int w)
{
struct timezone z ;
struct timeval time ;
int dt ;
int i ;
if( SerialLogFile == NULL )
return ;
gettimeofday(&time, &z) ;
dt = (time.tv_sec - timestamp.tv_sec)*1000 +
(time.tv_usec - timestamp.tv_usec)/1000 ;
if( w != which || dt > DTIME ) {
SerialLogFlush() ;
which = w ;
timestamp = time ;
}
while( len > 0 )
{
if( olen+len > sizeof(obuf) )
SerialLogFlush() ;
i = len > sizeof(obuf) ? sizeof(obuf) : len ;
bcopy(data, obuf+olen, i) ;
olen += i ;
len -= i ;
}
}

11
deps/Xmodem/seriallog.h vendored Normal file
View File

@@ -0,0 +1,11 @@
/* $Id: seriallog.h,v 1.2 2001/10/25 23:56:29 efalk Exp $ */
#ifndef SERIALLOG_H
#define SERIALLOG_H
extern FILE *SerialLogFile ;
extern void SerialLogFlush() ;
extern void SerialLog(const void *data, int len, int w) ;
#endif

133
deps/Xmodem/utils.c vendored Normal file
View File

@@ -0,0 +1,133 @@
#ifndef lint
static const char rcsid[] = "$Id: utils.c,v 1.2 2001/10/25 23:56:29 efalk Exp $" ;
#endif
/*
* Copyright (c) 1995 by Edward A. Falk
*/
/**********
*
*
* @ @ @@@@@ @@@ @ @@@@
* @ @ @ @ @ @
* @ @ @ @ @ @@@
* @ @ @ @ @ @
* @@@ @ @@@ @@@@@ @@@@
*
* UTILS - utilities used by xmodem library.
*
* Routines provided here:
*
*
* name (args)
* Brief description.
*
* int sendCancel()
*
* send cancel string <CAN><CAN>
*
*
* int sendFlush(c)
* char c ;
*
* flush input, send one character, return nonzero on error
*
*
* int sendChr(c)
* char c ;
*
* send one character, return nonzero on error
*
*
* int sendStr(str, len)
* char *str ;
* int len ;
*
* send string, return nonzero on error
*
*
* int calcChecksum(ptr, count)
* char *ptr ;
* int count ;
*
* compute checksum (used by xmodem)
*
*
* Edward A. Falk
*
* January, 1995
*
*
*
**********/
#include <sys/termios.h>
#include <sys/ioctl.h>
#include "xmodem.h"
int
sendCancel()
{
return sendFlush(CAN) || sendFlush(CAN) ;
}
/* send one character, return nonzero on error */
int
sendFlush(char c)
{
/* first, flush input port */
/* TODO: caller provide a way to do this? */
if( xmRfd == -1 )
return XmErrNotOpen ;
/* TODO: caller provides flush */
if( ioctl(xmRfd, TCFLSH, TCIFLUSH) == -1 )
return XmErrSys ;
return sendChr(c) ;
}
/* send one character, return nonzero on error */
int
sendChr(char c)
{
/* TODO: caller provide character output func? */
if( xmTfd == -1 )
return XmErrNotOpen ;
return write(xmTfd, &c, 1) ==1 ? 0 : XmErrSys ;
}
/* send multiple characters, return nonzero on error */
int
sendStr(char *str, int len)
{
/* TODO: caller provide character output func? */
if( xmTfd == -1 )
return XmErrNotOpen ;
return write(xmTfd, str, len) == len ? 0 : XmErrSys ;
}
/* compute checksum */
int
calcChecksum(char *ptr, int count)
{
register int csum = 0 ;
while( --count >= 0 )
csum += (u_char) *ptr++ ;
return csum & 255 ;
}

111
deps/Xmodem/xmodem.h vendored Normal file
View File

@@ -0,0 +1,111 @@
/* $Id: xmodem.h,v 1.2 2001/10/25 23:56:29 efalk Exp $ */
#include <sys/param.h>
typedef int bool ;
typedef enum {
Xmodem=0,
XmodemCrc=1,
WXmodem=2,
Ymodem=3,
YmodemG=4,
} Protocol ;
extern bool xmodem1k ; /* 1k blocks supported */
extern bool fileInfo ; /* ymodem: send file attributes? */
extern Protocol protocol ;
extern int xmTfd ; /* transmit file descriptor */
extern int xmRfd ; /* receive file descriptor */
extern int xmTimeout ; /* timeout, seconds */
extern char xmDefPath[MAXPATHLEN] ; /* default location (ymodem) */
extern char xmFilename[MAXPATHLEN] ; /* current filename */
/* error code definitions */
#define XmDone -1 /* done */
#define XmErrInt -2 /* internal error */
#define XmErrSys -3 /* system error, see errno */
#define XmErrNotOpen -4 /* communication channel not open */
#define XmErrCantOpen -5 /* can't open file, see errno */
#define XmErrInitTo -10 /* transmitter failed to respond to init req. */
#define XmErrSequence -11 /* packet received out of sequence */
#define XmErrCancel -12 /* cancelled by remote end */
#define XmErrRcvTo -13 /* remote end timed out during transfer */
#ifdef __STDC__
extern int XmodemRInit(char *path, Protocol p) ;
/* start receive protocol */
extern int XmodemRRcv(char c) ; /* call for each received char. */
extern int XmodemRTimeout() ; /* call if xmTimeout expires */
extern int XmodemRAbort() ; /* call to abort protocol */
extern int XmodemTInit(char *path, Protocol p) ;
/* start transmit protocol */
extern int XmodemTRcv(char c) ; /* call for each received char. */
extern int XmodemTTimeout() ; /* call if xmTimeout expires */
extern int XmodemTAbort() ; /* call to abort protocol */
extern int XmodemTFinish() ; /* call after last file sent (ymodem) */
#else
extern int XmodemRInit() ; /* start receive protocol */
extern int XmodemRRcv() ; /* call for each received char. */
extern int XmodemRTimeout() ; /* call if xmTimeout expires */
extern int XmodemRAbort() ; /* call to abort protocol */
extern int XmodemTInit() ; /* start transmit protocol */
extern int XmodemTRcv() ; /* call for each received char. */
extern int XmodemTTimeout() ; /* call if xmTimeout expires */
extern int XmodemTAbort() ; /* call to abort protocol */
#endif
/* INTERNAL */
#define SOH 1 /* ^A */
#define STX 2 /* ^B */
#define EOT 4 /* ^D */
#define ACK 6 /* ^F */
#define DLE 16 /* ^P */
#define XON 17 /* ^Q */
#define XOFF 19 /* ^S */
#define NAK 21 /* ^U */
#define SYN 22 /* ^V */
#define CAN 24 /* ^X */
#ifndef False
#define False 0
#define True 1
#endif
#define MAXERROR 10
#define INITTO 10 /* initialization timeout, basic xmodem */
#define INITTO2 3 /* initialization timeout */
#define PKTTO 5 /* in-packet receive timeout */
#define MAXPACKET 1024 /* max packet length */
#ifdef __STDC__
extern int sendCancel(), sendFlush(char),
sendChr(char), sendStr(char *,int) ;
extern int calcrc(char *ptr, int count) ;
extern int calcChecksum(char *ptr, int count) ;
#else
extern int sendCancel(), sendFlush(), sendChr(), sendStr() ;
extern int calcrc() ;
extern int calcChecksum() ;
#endif

417
deps/Xmodem/xmodemr.c vendored Normal file
View File

@@ -0,0 +1,417 @@
#ifndef lint
static const char rcsid[] = "$Id: xmodemr.c,v 1.1.1.1 2001/03/08 00:01:48 efalk Exp $" ;
#endif lint
/*
* Copyright (c) 1995 by Edward A. Falk
*/
/**********
*
*
* @ @ @ @ @@@ @@@@ @@@@@ @ @ @@@@
* @ @ @@ @@ @ @ @ @ @ @@ @@ @ @
* @ @ @ @ @ @ @ @ @@@ @ @ @ @@@@
* @ @ @ @ @ @ @ @ @ @ @ @ @ @ @
* @ @ @ @ @ @@@ @@@@ @@@@@ @ @ @ @ @
*
* XMODEMR - receiver side of xmodem/ymodem protocol
*
* Caller sets flags defined in xmodem.h as appropriate.
* (default is basic xmodem)
*
* This code is designed to be called from inside a larger
* program, so it is implemented as a state machine where
* practical.
*
*
* functions:
*
* XmodemRInit(char *filename, Protocol p)
* Initiate a receive
*
* XmodemRTimeout()
* called after timeout expired
*
* XmodemRRcv(char c)
* called after character received
*
* XmodemRAbort()
* abort transfer
*
* all functions return 0 on success, 1 on abort
*
*
*
* Edward A. Falk
*
* January, 1995
*
*
*
**********/
#include <stdio.h>
#include <sys/types.h>
#include "xmodem.h"
/* TODO: WXmodem */
bool xmodem1k = False ;
Protocol protocol = Xmodem ;
int xmTfd = -1 ;
int xmRfd = -1 ;
int xmTimeout = 0 ;
char xmDefPath[MAXPATHLEN] ;
char xmFilename[MAXPATHLEN] ;
typedef enum {
Start, /* waiting to begin */
Init, /* sent initial NAK, 'C' or 'W' */
Packet, /* receiving a packet */
Wait, /* wait for start of next packet */
} XmodemState ;
static bool ymodem ;
static XmodemState state = Start ;
static int errorCount = 0 ;
static int errorCount2 ;
static int ignoreCount ;
static int eotCount ; /* count EOT's, reject first one */
static int inCount ; /* characters received this packet */
static int pktLen ; /* length of this packet data */
static int pktHdrLen ; /* id, cmpl, checksum or crc */
static char packet[MAXPACKET+5], *optr ;
static int packetId ; /* id of last received packet */
static int packetCount ; /* # packets received */
static FILE *ofile ; /* output file fd */
static int fileLen, fileDate, fileMode ;
static int XmodemRStart() ;
static int processPacket() ;
static int rejectPacket() ;
static int acceptPacket() ;
int
XmodemRInit( char *file, Protocol prot )
{
int err ;
state = Start ;
protocol = prot ;
ymodem = prot == Ymodem || prot == YmodemG ;
if( ymodem )
strcpy(xmDefPath, file) ;
else
strcpy(xmFilename, file) ;
eotCount = errorCount = errorCount2 = 0 ;
if( err=XmodemRStart() )
return err ;
state = Init ;
packetId = ymodem ? 255 : 0 ;
packetCount = 0 ;
pktHdrLen = protocol == Xmodem ? 3 : 4 ;
return 0 ;
}
/* send startup character */
static int
XmodemRStart()
{
static char pchars[5] = {NAK,'C','W','C','C'} ;
static int timeouts[5] = {INITTO, INITTO2, INITTO2, INITTO, INITTO} ;
char c = pchars[(int)protocol] ;
int err ;
if( err=sendFlush(c) )
return err ;
xmTimeout = timeouts[(int)protocol] ;
return 0 ;
}
int
XmodemRRcv(char c)
{
errorCount = 0 ;
switch( state ) {
case Start: /* shouldn't happen, ignore */
if( c == CAN )
return XmErrCancel ;
break ;
case Init: /* waiting */
case Wait:
switch( c ) {
case SOH:
case STX:
pktLen = c == STX ? 1024 : 128 ;
inCount = 0 ;
optr = packet ;
state = Packet ;
xmTimeout = PKTTO ;
break ;
case EOT:
if( ++eotCount > 1 ) {
sendFlush(ACK) ;
if( ymodem )
return XmodemRInit() ; /* restart protocol */
else
return XmDone ;
}
else
return rejectPacket() ; /* make xmitter try again */
case CAN: return XmErrCancel ;
default: /* ignore all others */
if( ++ignoreCount > 1030 ) {
ignoreCount = 0 ;
return sendFlush(NAK) ;
}
break ;
}
break ;
case Packet: /* mid packet */
*optr++ = c ;
if( ++inCount >= pktLen + pktHdrLen )
ProcessPacket() ;
break ;
}
return 0 ;
}
int
XmodemRTimeout()
{
if( ++errorCount > MAXERROR )
return state == Init ? XmErrInitTo : XmErrRcvTo ;
switch( state ) {
case Start: return -1 ; /* shouldn't happen */
case Init:
if( ++errorCount2 >= 3 )
switch( protocol ) {
case WXmodem: protocol = XmodemCrc ; errorCount2 = 0 ; break ;
case XmodemCrc: protocol = Xmodem ; pktHdrLen = 3 ; break ;
}
return XmodemRStart() ;
case Wait: /* timeout while waiting */
case Packet: /* timeout in mid packet */
return rejectPacket() ;
}
}
int
XmodemRAbort()
{
return sendCancel() ;
}
static int
ProcessPacket()
{
int id = (u_char)packet[0] ;
int idc = (u_char)packet[1] ;
int i ;
if( idc != 255-id )
return rejectPacket() ;
if( id == packetId ) /* duplicate */
return acceptPacket() ;
if( id != (packetId+1)%256 ) { /* out of sequence */
(void) sendCancel() ;
return XmErrSequence ;
}
if( protocol == Xmodem )
{
/* compute checksum */
register int csum = calcChecksum(packet+2, pktLen) ;
if( csum != (u_char) packet[2+pktLen] )
return rejectPacket() ;
}
else
{
int crc0 = (u_char)packet[pktLen+2] << 8 | (u_char)packet[pktLen+3] ;
int crc1 = calcrc(packet+2, pktLen) ;
if( crc0 != crc1 )
return rejectPacket() ;
}
/* it's a good packet */
packetId = (packetId+1)%256 ;
/* is this the first packet? */
if( packetCount == 0 )
{
if( ymodem )
{
if( packet[2] == '\0' ) /* last file */
{
(void) acceptPacket() ;
return XmDone ;
}
if( packet[2] == '/' )
strcpy(xmFilename, packet+2) ;
else {
strcpy(xmFilename, xmDefPath) ;
strcat(xmFilename, packet+2) ;
}
fileLen = fileDate = fileMode = -1 ;
sscanf(packet+2+strlen(packet)+1, "%d %o %o",
&fileLen, &fileDate, &fileMode) ;
}
if( (ofile = fopen(xmFilename, "w")) == NULL ) {
sendCancel() ;
return XmErrCantOpen ;
}
if( ymodem ) {
packetCount = 1 ;
(void) acceptPacket() ;
return sendFlush('C') ;
}
else
state = Packet ;
}
++packetCount ;
/* TODO: ymodem: if this is last packet, truncate it */
if( (i=fwrite(packet+2, 1, pktLen, ofile)) != pktLen )
{
sendCancel() ;
return XmErrSys ;
}
else
return acceptPacket() ;
}
static int
rejectPacket()
{
state = Wait ;
xmTimeout = INITTO ;
return sendFlush(NAK) ;
}
static int
acceptPacket()
{
state = Wait ;
xmTimeout = INITTO ;
return sendFlush(ACK) ;
}
#ifdef COMMENT /* stand-alone testing */
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/termios.h>
main(argc,argv)
int argc ;
char **argv ;
{
struct termios old_settings, new_settings ;
fd_set readfds ;
struct timeval timeout ;
int i ;
int len ;
char buffer[1024] ;
bool done = False ;
if( argc < 2 )
exit(2) ;
xmTfd = xmRfd = open(argv[1], O_RDWR) ;
if( xmTfd == -1 )
exit(1) ;
tcgetattr(xmTfd,&old_settings) ;
new_settings = old_settings ;
new_settings.c_iflag &=
~(ISTRIP|INLCR|IGNCR|ICRNL|IUCLC|IXON|IXOFF|IMAXBEL) ;
new_settings.c_oflag = 0 ;
new_settings.c_cflag = B300|CS8|CREAD|CLOCAL ;
new_settings.c_lflag = 0 ;
new_settings.c_cc[VMIN] = 32 ;
new_settings.c_cc[VTIME] = 1 ;
tcsetattr(xmTfd,TCSADRAIN, &new_settings) ;
xmodem1k = 0 ;
done = XmodemRInit("foo", XmodemCrc) != 0 ;
#ifdef COMMENT
xmodem1k = 1 ;
done = XmodemRInit("./", Ymodem) != 0 ;
#endif /* COMMENT */
while(!done)
{
FD_ZERO(&readfds) ;
FD_SET(xmTfd, &readfds) ;
timeout.tv_sec = xmTimeout ;
timeout.tv_usec = 0 ;
i = select(xmTfd+1, &readfds,NULL,NULL, &timeout) ;
if( i<0 )
perror("select") ;
else if( i==0 )
done = XmodemRTimeout() != 0 ;
else {
len = read(xmTfd, buffer, sizeof(buffer)) ;
for(i=0; !done && i<len; ++i)
done = XmodemRRcv(buffer[i]) != 0 ;
}
}
tcsetattr(xmTfd,TCSADRAIN, &old_settings) ;
exit(0) ;
}
#endif /* COMMENT */

410
deps/Xmodem/xmodemt.c vendored Normal file
View File

@@ -0,0 +1,410 @@
#ifndef lint
static const char rcsid[] = "$Id: xmodemt.c,v 1.2 2001/10/25 23:56:29 efalk Exp $" ;
#endif
/*
* Copyright (c) 1995 by Edward A. Falk
*/
/**********
*
*
* @ @ @ @ @@@ @@@@ @@@@@ @ @ @@@@@
* @ @ @@ @@ @ @ @ @ @ @@ @@ @
* @ @ @ @ @ @ @ @ @@@ @ @ @ @
* @ @ @ @ @ @ @ @ @ @ @ @ @ @
* @ @ @ @ @ @@@ @@@@ @@@@@ @ @ @ @
*
* XMODEMT - transmit side of xmodem protocol
*
* Caller sets flags defined in xmodem.h as appropriate.
* (default is basic xmodem)
*
* This code is designed to be called from inside a larger
* program, so it is implemented as a state machine where
* practical.
*
* functions:
*
* XmodemTInit(char *filename, Protocol p)
* Initiate a receive
*
* XmodemTTimeout()
* called after timeout expired
*
* XmodemTRcv(char c)
* called after character received
*
* XmodemTFinish()
* last file (ymodem)
*
* XmodemTAbort()
* abort transfer
*
* all functions return 0 on success, 1 on abort
*
* Edward A. Falk
*
* January, 1995
*
*
*
**********/
#include <stdio.h>
#include <sys/types.h>
#include "xmodem.h"
bool fileInfo = False ;
/* TODO: WXmodem, YmodemG */
typedef enum {
File, /* waiting for initial protocol character */
FileWait, /* sent file header, waiting for ACK */
Start, /* waiting to begin */
Wait, /* sent a packet, waiting for ACK */
Eot, /* sent an EOT, waiting for ACK */
EndWait, /* sent null filename, waiting for ACK */
} XmodemState ;
static XmodemState state = Start ;
static bool ymodem ;
static bool useCrc ; /* receiver wants crc */
static int pktLen ; /* length of this packet data */
static int pktMaxLen ;
static char packet[MAXPACKET] ;
static char pktHdr[3], pktCrc[2] ;
static int packetId ; /* id of last received packet */
static int packetCount ; /* # packets received */
static FILE *ifile = NULL ; /* input file fd */
static int fileLen, fileDate, fileMode ;
static int sendFilename() ;
static int sendPacket() ;
static int buildPacket() ;
static int resendPacket() ;
int
XmodemTInit( char *file, Protocol prot )
{
int err ;
protocol = prot ;
ymodem = prot == Ymodem || prot == YmodemG ;
state = ymodem ? File : Start ;
strcpy(xmFilename, file) ;
if( (ifile = fopen(xmFilename, "r")) == NULL ) {
sendCancel() ;
return XmErrCantOpen ;
}
packetId = 1 ;
packetCount = 0 ;
pktMaxLen = xmodem1k ? 1024 : 128 ;
xmTimeout = 60 ;
return 0 ;
}
int
XmodemTRcv(char c)
{
if( c == CAN ) {
if( ifile != NULL )
fclose(ifile) ;
return XmErrCancel ;
}
switch( state ) {
case File: /* waiting for command, ymodem */
switch( c ) {
case NAK: useCrc = False ; return sendFilename() ;
case 'C': useCrc = True ; return sendFilename() ;
}
break ;
case FileWait: /* waiting for filename ACK */
switch( c ) {
case NAK: return resendPacket() ;
case ACK: state = Start ; return 0 ;
}
case Start: /* waiting for command, data */
switch( c ) {
case NAK: /* wants checksums */
if( !ymodem )
protocol = Xmodem ;
useCrc = False ;
return sendPacket() ;
case 'C': useCrc = True ; return sendPacket() ;
case 'W':
if( !ymodem ) {
protocol = WXmodem ;
useCrc = True ;
/* TODO: WXmodem */
}
}
break ;
case Wait: /* waiting for ACK */
switch( c ) {
case ACK: return sendPacket() ;
case NAK: return resendPacket() ;
}
break ; /* ignore all other characters */
case Eot: /* waiting for ACK after EOT */
switch( c ) {
case ACK: return XmDone ;
case NAK: return sendChr(EOT) ;
}
break ;
case EndWait: /* waiting for filename ACK */
switch( c ) {
case NAK: return resendPacket() ;
case ACK: return XmDone ;
}
}
return 0 ;
}
static int
sendFilename()
{
int i ;
char *ptr ;
pktLen = 128 ;
/* TODO: protect against long filenames */
strcpy(packet, xmFilename) ;
ptr = packet + strlen(packet) + 1 ;
/* TODO: get file info */
if( fileInfo ) {
sprintf(ptr, "%d %o %o %o", 0,0,0100644) ;
ptr += strlen(ptr) + 1 ;
}
/* TODO: what if file desc buffer too big? */
if( ptr > packet+128 )
pktLen = 1024 ;
i = pktLen - (ptr-packet) ;
bzero(ptr, i) ;
state = FileWait ;
packetId = 0 ;
return buildPacket() ;
}
int
XmodemTFinish()
{
int i ;
char *ptr ;
pktLen = 128 ;
bzero(packet, pktLen) ;
state = EndWait ;
packetId = 0 ;
return buildPacket() ;
}
static char *bufptr ;
static int buflen = 0 ;
static int
sendPacket()
{
int i ;
/* This code assumes that a incomplete reads can only happen
* after EOF. This will fail with pipes.
* TODO: try to make pipes work.
*/
state = Wait ;
if( buflen > 0 ) /* previous incomplete packet */
{
memcpy(packet, bufptr, 128) ;
bufptr += 128 ;
if( buflen < 128 )
for(i=buflen; i<128; ++i)
packet[i] = 0x1a ;
buflen -= 128 ;
pktLen = 128 ;
return buildPacket() ;
}
if( (i=fread(packet, 1,pktMaxLen, ifile)) <= 0 ) /* EOF */
{
state = Eot ;
return sendChr(EOT) ;
}
else if( i == pktMaxLen ) /* full buffer */
{
pktLen = i ;
return buildPacket() ;
}
buflen = i ;
bufptr = packet ;
pktLen = 128 ;
return buildPacket() ;
}
static int
buildPacket()
{
int i ;
pktHdr[0] = pktLen == 128 ? SOH : STX ;
pktHdr[1] = (char)packetId ;
pktHdr[2] = (char)(255-packetId) ;
++packetId ;
if( useCrc ) {
i = calcrc(packet, pktLen) ;
pktCrc[0] = (char) (i>>8) ;
pktCrc[1] = (char) (i & 0xff) ;
}
else
pktCrc[0] = (char) calcChecksum(packet, pktLen) ;
return resendPacket() ;
}
static int
resendPacket()
{
int i ;
(i=sendStr(pktHdr, 3)) || (i=sendStr(packet, pktLen)) ||
(i=sendStr(pktCrc, useCrc?2:1)) ;
return i ;
}
int
XmodemTTimeout()
{
switch( state ) {
case File:
case Start:
return XmErrInitTo ;
case FileWait:
case Wait:
case Eot:
return XmErrRcvTo ;
}
}
int
XmodemTAbort()
{
return sendCancel() ;
}
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/termios.h>
main(argc,argv)
int argc ;
char **argv ;
{
struct termios old_settings, new_settings ;
fd_set readfds ;
struct timeval timeout ;
int i ;
int len ;
char buffer[1024] ;
bool done = False ;
int filecount = 0 ;
if( argc < 2 )
exit(2) ;
xmTfd = xmRfd = open(argv[1], O_RDWR) ;
if( xmTfd == -1 )
exit(1) ;
tcgetattr(xmTfd,&old_settings) ;
new_settings = old_settings ;
new_settings.c_iflag &=
~(ISTRIP|INLCR|IGNCR|ICRNL|IUCLC|IXON|IXOFF|IMAXBEL) ;
new_settings.c_oflag = 0 ;
new_settings.c_cflag = B300|CS8|CREAD|CLOCAL ;
new_settings.c_lflag = 0 ;
new_settings.c_cc[VMIN] = 32 ;
new_settings.c_cc[VTIME] = 1 ;
tcsetattr(xmTfd,TCSADRAIN, &new_settings) ;
xmodem1k = 1 ;
done = XmodemTInit("xmodem.h", Ymodem) != 0 ;
while(!done)
{
FD_ZERO(&readfds) ;
FD_SET(xmTfd, &readfds) ;
timeout.tv_sec = xmTimeout ;
timeout.tv_usec = 0 ;
i = select(xmTfd+1, &readfds,NULL,NULL, &timeout) ;
if( i<0 )
perror("select") ;
else if( i==0 )
done = XmodemTTimeout() != 0 ;
else {
len = read(xmTfd, buffer, sizeof(buffer)) ;
for(i=0; !done && i<len; ++i)
done = XmodemTRcv(buffer[i]) != 0 ;
}
if( done ) {
switch( ++filecount ) {
case 1:
done = XmodemTInit("crc.c", Ymodem) != 0 ;
break ;
case 2:
done = XmodemTFinish() ;
break ;
case 3: break ;
}
}
}
tcsetattr(xmTfd,TCSADRAIN, &old_settings) ;
exit(0) ;
}

900
deps/Xmodem/zmodem.c vendored Normal file
View File

@@ -0,0 +1,900 @@
#ifndef lint
static const char rcsid[] = "$Id: zmodem.c,v 1.1.1.1 2001/03/08 00:01:48 efalk Exp $" ;
#endif
/*
* Copyright (c) 1995 by Edward A. Falk
*/
/**********
*
*
* @@@@@ @ @ @@@ @@@@ @@@@@ @ @
* @ @@ @@ @ @ @ @ @ @@ @@
* @ @ @ @ @ @ @ @ @@@ @ @ @
* @ @ @ @ @ @ @ @ @ @ @ @
* @@@@@ @ @ @ @@@ @@@@ @@@@@ @ @ @
*
* ZMODEM - main logic parser for zmodem library
*
*
* Routines provided here:
*
*
* name (args)
* Brief description.
*
* int ZmodemRcv(u_char *buffer, int len, ZModem *info)
* Call whenever characters are received. If this function
* returns ZmDone, previous function has completed successfully,
* either call ZmodemTFile() to start next file, or call
* ZmodemTFinish() to terminate the session.
*
*
* int
* ZmodemTimeout(ZModem *info)
* Call whenever the timeout period expires and no
* characters have been received.
*
* int
* ZmodemAttention(ZModem *info)
* Call whenever the attention sequence has been received
* from the remote end. It is safe to call this function
* from an interrupt handler.
*
* int
* ZmodemAbort(ZModem *info)
* Call to abort transfer. Physical connection remains
* open until you close it.
*
*
*
*
* Edward A. Falk
*
* January, 1995
*
*
*
**********/
#include <stdio.h>
/****
*
* Constants, typedefs, externals, globals, statics, macros, block data
*
****/
/* TODO: sample input before initial send */
/* TODO: more intelligent timeout dispatch */
/* TODO: read all pending input before sending next data packet out */
/* TODO: if received ZDATA while waiting for ZFILE/ZFIN, it's probably
leftovers */
/* TODO: enable flow control for zmodem, disable for X/YModem */
#include <ctype.h>
#include <errno.h>
#include <string.h>
#include "zmodem.h"
#include "crctab.h"
static u_char zeros[4] = {0,0,0,0} ;
extern int YrcvChar( char c, register ZModem *info ) ;
extern int YrcvTimeout( register ZModem *info ) ;
extern void ZIdleStr(u_char *buffer, int len, ZModem *info) ;
/* LEXICAL BOX: handle characters received from remote end.
* These may be header, data or noise.
*
* This section is a finite state machine for parsing headers
* and reading input data. The info->chrCount field is effectively
* the state variable.
*/
static int FinishChar( char c, register ZModem *info ) ;
static int DataChar( u_char c, register ZModem *info ) ;
static int HdrChar( u_char c, register ZModem *info ) ;
static int IdleChar(u_char c, register ZModem *info) ;
extern int YsendChar() ;
static int ZProtocol(), ZDataReceived() ;
int
ZmodemRcv( register u_char *str, int len, register ZModem *info )
{
register u_char c ;
int err ;
info->rcvlen = len ;
while( --info->rcvlen >= 0 )
{
c = *str++ ;
if( c == CAN ) {
if( ++info->canCount >= 5 ) {
ZStatus(RmtCancel, 0, NULL) ;
return ZmErrCancel ;
}
}
else
info->canCount = 0 ;
if( info->InputState == Ysend ) {
if( (err = YsendChar(c, info)) )
return err ;
}
else if( info->InputState == Yrcv ) {
if( (err = YrcvChar(c, info)) )
return err ;
}
else if( c != XON && c != XOFF )
{
/* now look at what we have */
switch( info->InputState )
{
case Idle:
if( (err = IdleChar(c, info)) )
return err ;
break ;
case Inhdr:
if( (err = HdrChar(c, info)) )
return err ;
break ;
case Indata:
if( (err = DataChar(c, info)) )
return err ;
break ;
case Finish:
if( (err = FinishChar(c, info)) )
return err ;
break ;
default:
break ;
}
}
}
return 0 ;
}
/* handle character input while idling
* looking for ZPAD-ZDLE sequence which introduces a header
*/
static int
IdleChar(u_char c, register ZModem *info)
{
if( info->chrCount == 0 )
{
if( c == ZPAD )
++info->chrCount ;
else if( info->state == Sending && ++info->noiseCount > MaxNoise )
info->waitflag = 1 ;
else if( info->state == TStart && (c == 'C' || c == 'G' || c == NAK) )
{
/* switch to ymodem */
info->state = YTStart ;
info->InputState = Ysend ;
info->Protocol = YMODEM ;
return YsendChar(c, info) ;
}
else
ZIdleStr(&c, 1, info) ;
}
else
{
switch( c ) {
case ZPAD:
++info->chrCount ;
break ;
case ZDLE:
info->InputState = Inhdr ;
info->chrCount=0 ;
break ;
default:
while( --info->chrCount >= 0 )
ZIdleStr((u_char *)"*", 1, info) ;
info->chrCount = 0 ;
break ;
}
}
return 0 ;
}
static u_int
rcvHex( u_int i, char c )
{
if( c <= '9' )
c -= '0' ;
else if( c <= 'F' )
c -= 'A'-10 ;
else
c -= 'a'-10 ;
return (i<<4)+c ;
}
/* handle character input in a header */
static int
HdrChar( u_char c, register ZModem *info )
{
int i ;
int crc=0 ;
if( c == ZDLE ) {
info->escape = 1 ;
return 0 ;
}
if( info->escape ) {
info->escape = 0 ;
switch( c ) {
case ZRUB0: c = 0177 ; break ;
case ZRUB1: c = 0377 ; break ;
default: c ^= 0100 ; break ;
}
}
if( info->chrCount == 0 ) { /* waiting for format */
switch( c ) {
case ZHEX:
case ZBIN:
case ZBIN32:
info->DataType = c ;
info->chrCount = 1 ;
info->crc = (info->DataType != ZBIN32) ? 0 : 0xffffffffL ;
memset(info->hdrData,0,sizeof(info->hdrData)) ;
break ;
default:
info->InputState = Idle ;
info->chrCount = 0 ;
return ZXmitHdrHex(ZNAK, zeros, info) ;
}
return 0 ;
}
switch( info->DataType ) {
/* hex header is 14 hex digits, cr, lf. Optional xon is ignored */
case ZHEX:
if( info->chrCount <= 14 && !isxdigit(c) ) {
info->InputState = Idle ;
info->chrCount = 0 ;
return ZXmitHdrHex(ZNAK, zeros, info) ;
}
if( info->chrCount <= 14 ) {
i = (info->chrCount-1)/2 ;
info->hdrData[i] = rcvHex(info->hdrData[i], c) ;
}
if( info->chrCount == 16 ) {
crc = 0 ;
for(i=0; i<7; ++i)
crc = updcrc(info->hdrData[i], crc) ;
info->InputState = Idle ;
info->chrCount = 0 ;
if( (crc&0xffff) != 0 )
return ZXmitHdrHex(ZNAK, zeros, info) ;
else
return ZProtocol(info) ;
}
else
++info->chrCount ;
break ;
case ZBIN:
/* binary header is type, 4 bytes data, 2 bytes CRC */
info->hdrData[info->chrCount-1] = c ;
info->crc = updcrc(c, info->crc) ;
if( ++info->chrCount > 7 ) {
info->InputState = Idle ;
info->chrCount = 0 ;
if( (crc&0xffff) != 0 )
return ZXmitHdrHex(ZNAK, zeros, info) ;
else
return ZProtocol(info) ;
}
break ;
case ZBIN32:
/* binary32 header is type, 4 bytes data, 4 bytes CRC */
info->hdrData[info->chrCount-1] = c ;
info->crc = UPDC32(c, info->crc) ;
if( ++info->chrCount > 9 ) {
info->InputState = Idle ;
info->chrCount = 0 ;
if( info->crc != 0xdebb20e3 ) /* see note below */
return ZXmitHdrHex(ZNAK, zeros, info) ;
else
return ZProtocol(info) ;
}
break ;
}
return 0 ;
}
/* handle character input in a data buffer */
static int
DataChar( u_char c, register ZModem *info )
{
if( c == ZDLE ) {
info->escape = 1 ;
return 0 ;
}
if( info->escape ) {
info->escape = 0 ;
switch( c ) {
case ZCRCE:
case ZCRCG:
case ZCRCQ:
case ZCRCW:
info->PacketType = c ;
info->crcCount = (info->DataType == ZBIN32) ? 4 : 2 ;
if( info->DataType == ZBIN )
info->crc = updcrc(c, info->crc) ;
else
info->crc = UPDC32(c, info->crc) ;
return 0 ;
case ZRUB0: c = 0177 ; break ;
case ZRUB1: c = 0377 ; break ;
default: c ^= 0100 ; break ;
}
}
switch( info->DataType ) {
/* TODO: are hex data packets ever used? */
case ZBIN:
info->crc = updcrc(c, info->crc) ;
if( info->crcCount == 0 )
info->buffer[info->chrCount++] = c ;
else if( --info->crcCount == 0 ) {
return ZDataReceived(info, (info->crc&0xffff) == 0) ;
}
break ;
case ZBIN32:
info->crc = UPDC32(c, info->crc) ;
if( info->crcCount == 0 )
info->buffer[info->chrCount++] = c ;
else if( --info->crcCount == 0 ) {
return ZDataReceived(info, info->crc == 0xdebb20e3) ;
}
break ;
}
return 0 ;
}
/* wait for "OO" */
static int
FinishChar( char c, register ZModem *info )
{
if( c == 'O' ) {
if( ++info->chrCount >= 2 )
return ZmDone ;
}
else
info->chrCount = 0 ;
return 0 ;
}
int ZPF() ;
int Ignore() ;
int AnswerChallenge() ;
int GotAbort() ;
int GotCancel() ;
int GotCommand() ;
int GotStderr() ;
int RetDone() ;
static int GotCommandData() ;
static int GotStderrData() ;
/* PROTOCOL LOGIC: This section of code handles the actual
* protocol. This is also driven by a finite state machine
*
* State tables are sorted by approximate frequency order to
* reduce search time.
*/
/* Extra ZRINIT headers are the receiver trying to resync. */
/* If compiling for Send Only or Receive Only, convert table
* entries to no-ops so we don't have to link zmodem[rt].o
*/
#if SendOnly
#define RStartOps DoneOps
#define RSinitWaitOps DoneOps
#define RFileNameOps DoneOps
#define RCrcOps DoneOps
#define RFileOps DoneOps
#define RDataOps DoneOps
#define RFinishOps DoneOps
#define GotFileName Ignore
#define ResendCrcReq Ignore
#define GotSinitData Ignore
#define ResendRpos Ignore
#define GotFileData Ignore
#define SendRinit Ignore
#else
extern StateTable RStartOps[] ;
extern StateTable RSinitWaitOps[] ;
extern StateTable RFileNameOps[] ;
extern StateTable RCrcOps[] ;
extern StateTable RFileOps[] ;
extern StateTable RDataOps[] ;
extern StateTable RFinishOps[] ;
extern int GotFileName() ;
extern int ResendCrcReq() ;
extern int GotSinitData() ;
extern int ResendRpos() ;
extern int GotFileData() ;
extern int SendRinit() ;
#endif
#if RcvOnly
#define TStartOps DoneOps
#define TInitOps DoneOps
#define FileWaitOps DoneOps
#define CrcWaitOps DoneOps
#define SendingOps DoneOps
#define SendDoneOps DoneOps
#define SendWaitOps DoneOps
#define SendEofOps DoneOps
#define TFinishOps DoneOps
#define SendMoreFileData Ignore
#else
extern StateTable TStartOps[] ;
extern StateTable TInitOps[] ;
extern StateTable FileWaitOps[] ;
extern StateTable CrcWaitOps[] ;
extern StateTable SendingOps[] ;
extern StateTable SendDoneOps[] ;
extern StateTable SendWaitOps[] ;
extern StateTable SendEofOps[] ;
extern StateTable TFinishOps[] ;
extern int SendMoreFileData() ;
#endif
static StateTable CommandDataOps[] = {
#ifdef COMMENT
{ZRQINIT,f,1,1},
{ZRINIT,f,1,1},
{ZSINIT,f,1,1},
{ZACK,f,1,1},
{ZFILE,f,1,1},
{ZSKIP,f,1,1},
{ZNAK,f,1,1},
{ZABORT,f,1,1,TFinish},
{ZFIN,f,1,1},
{ZRPOS,f,1,1},
{ZDATA,f,1,1},
{ZEOF,f,1,1},
{ZFERR,f,1,1,TFinish},
{ZCRC,f,1,1},
{ZCHALLENGE,f,1,1},
{ZCOMPL,f,1,1},
{ZCAN,f,1,1},
{ZFREECNT,f,1,1},
{ZCOMMAND,f,1,1},
{ZSTDERR,f,1,1},
#endif /* COMMENT */
{99,ZPF,0,0,CommandData},
} ;
static StateTable CommandWaitOps[] = {
#ifdef COMMENT
{ZRQINIT,f,1,1},
{ZRINIT,f,1,1},
{ZSINIT,f,1,1},
{ZACK,f,1,1},
{ZFILE,f,1,1},
{ZSKIP,f,1,1},
{ZNAK,f,1,1},
{ZABORT,f,1,1,TFinish},
{ZFIN,f,1,1},
{ZRPOS,f,1,1},
{ZDATA,f,1,1},
{ZEOF,f,1,1},
{ZFERR,f,1,1,TFinish},
{ZCRC,f,1,1},
{ZCHALLENGE,f,1,1},
{ZCOMPL,f,1,1},
{ZCAN,f,1,1},
{ZFREECNT,f,1,1},
{ZCOMMAND,f,1,1},
{ZSTDERR,f,1,1},
#endif /* COMMENT */
{99,ZPF,0,0,CommandWait},
} ;
static StateTable StderrDataOps[] = {
#ifdef COMMENT
{ZRQINIT,f,1,1},
{ZRINIT,f,1,1},
{ZSINIT,f,1,1},
{ZACK,f,1,1},
{ZFILE,f,1,1},
{ZSKIP,f,1,1},
{ZNAK,f,1,1},
{ZABORT,f,1,1,TFinish},
{ZFIN,f,1,1},
{ZRPOS,f,1,1},
{ZDATA,f,1,1},
{ZEOF,f,1,1},
{ZFERR,f,1,1,TFinish},
{ZCRC,f,1,1},
{ZCHALLENGE,f,1,1},
{ZCOMPL,f,1,1},
{ZCAN,f,1,1},
{ZFREECNT,f,1,1},
{ZCOMMAND,f,1,1},
{ZSTDERR,f,1,1},
#endif /* COMMENT */
{99,ZPF,0,0,StderrData},
} ;
static StateTable DoneOps[] = {
{99,ZPF,0,0,Done},
} ;
static StateTable *tables[] = {
RStartOps,
RSinitWaitOps,
RFileNameOps,
RCrcOps,
RFileOps,
RDataOps,
RDataOps, /* RDataErr is the same as RData */
RFinishOps,
TStartOps,
TInitOps,
FileWaitOps,
CrcWaitOps,
SendingOps,
SendWaitOps,
SendDoneOps,
SendEofOps,
TFinishOps,
CommandDataOps,
CommandWaitOps,
StderrDataOps,
DoneOps,
} ;
char *hdrnames[] = {
"ZRQINIT",
"ZRINIT",
"ZSINIT",
"ZACK",
"ZFILE",
"ZSKIP",
"ZNAK",
"ZABORT",
"ZFIN",
"ZRPOS",
"ZDATA",
"ZEOF",
"ZFERR",
"ZCRC",
"ZCHALLENGE",
"ZCOMPL",
"ZCAN",
"ZFREECNT",
"ZCOMMAND",
"ZSTDERR",
} ;
/* This function is called (indirectly) by the ZmodemRcv()
* function when a full header has been received.
*/
static int
ZProtocol( register ZModem *info )
{
register StateTable *table ;
zmodemlog("received %s: %2.2x %2.2x %2.2x %2.2x = %lx\n",
hdrnames[info->hdrData[0]], info->hdrData[1],
info->hdrData[2], info->hdrData[3], info->hdrData[4],
ZDec4(info->hdrData+1)) ;
/* Flags are sent in F3 F2 F1 F0 order. Data is sent in P0 P1 P2 P3 */
info->timeoutCount = 0 ;
info->noiseCount = 0 ;
table = tables[(int)info->state] ;
while( table->type != 99 && table->type != info->hdrData[0] )
++table ;
zmodemlog(" state %s => %s, iflush=%d, oflush=%d, call %x\n",
sname(info), sname2(table->newstate), table->IFlush,
table->OFlush, table->func) ;
info->state = table->newstate ;
if( table->IFlush ) {info->rcvlen = 0 ; ZIFlush(info) ;}
if( table->OFlush ) ZOFlush(info) ;
return table->func(info) ;
}
static int
ZDataReceived( register ZModem *info, int crcGood )
{
switch( info->state ) {
case RSinitWait: return GotSinitData(info, crcGood) ;
case RFileName: return GotFileName(info, crcGood) ;
case RData: return GotFileData(info, crcGood) ;
case CommandData: return GotCommandData(info, crcGood) ;
case StderrData: return GotStderrData(info, crcGood) ;
default: return ZPF(info) ;
}
}
int
ZmodemTimeout( register ZModem *info )
{
/* timed out while waiting for input */
++info->timeoutCount ;
zmodemlog("timeout %d [%s]\n", info->timeoutCount, sname(info) ) ;
switch( info->state ) {
/* receive */
case RStart: /* waiting for INIT frame from other end */
if( info->timeoutCount > 4 )
return YmodemRInit(info) ;
case RSinitWait:
case RFileName:
if( info->timeout > 0 )
ZStatus(SndTimeout, info->timeoutCount, NULL) ;
if( info->timeoutCount > 4 )
return ZmErrRcvTo ;
info->state = RStart ;
return SendRinit(info) ;
case RCrc:
case RFile:
case RData:
ZStatus(SndTimeout, info->timeoutCount, NULL) ;
if( info->timeoutCount > 2 ) {
info->timeoutCount = 0 ;
info->state = RStart ;
return SendRinit(info) ;
}
return info->state == RCrc ? ResendCrcReq(info) : ResendRpos(info) ;
case RFinish:
ZStatus(SndTimeout, info->timeoutCount, NULL) ;
return ZmDone ;
case YRStart:
case YRDataWait:
case YRData:
case YREOF:
return YrcvTimeout(info) ;
/* transmit */
case TStart: /* waiting for INIT frame from other end */
case TInit: /* sent INIT, waiting for ZACK */
case FileWait: /* sent file header, waiting for ZRPOS */
case CrcWait: /* sent file crc, waiting for ZRPOS */
case SendWait: /* waiting for ZACK */
case SendEof: /* sent EOF, waiting for ZACK */
case TFinish: /* sent ZFIN, waiting for ZFIN */
case YTStart:
case YTFile:
case YTDataWait:
case YTData:
case YTEOF:
case YTFin:
ZStatus(RcvTimeout,0,NULL) ;
return ZmErrRcvTo ;
case Sending: /* sending data subpackets, ready for int */
return SendMoreFileData(info) ;
/* general */
case CommandData: /* waiting for command data */
case StderrData: /* waiting for stderr data */
return ZmErrSndTo ;
case CommandWait: /* waiting for command to execute */
return ZmErrCmdTo ;
case Done:
return ZmDone ;
default:
return 0 ;
}
}
int
ZmodemAttention( register ZModem *info )
{
/* attention received from remote end */
if( info->state == Sending ) {
ZOFlush(info) ;
info->interrupt = 1 ;
}
return 0 ;
}
int
ZmodemAbort( register ZModem *info )
{
static u_char canistr[] = {
CAN,CAN,CAN,CAN,CAN,CAN,CAN,CAN,8,8,8,8,8,8,8,8,8,8
} ;
info->state = Done ;
ZIFlush(info) ;
ZOFlush(info) ;
return ZXmitStr(canistr, sizeof(canistr), info) ;
}
/* used to completely ignore headers */
int
Ignore( ZModem *info )
{
return 0 ;
}
/* ignore header contents, return ZmDone */
int
RetDone( ZModem *info )
{
return ZmDone ;
}
/* ignore header contents, return ZmErrCancel */
int
GotCancel( ZModem *info )
{
return ZmErrCancel ;
}
/* utility: set up to receive a data packet */
int
dataSetup( register ZModem *info )
{
info->InputState = Indata ;
info->chrCount = 0 ;
info->crcCount = 0 ;
info->crc = (info->DataType != ZBIN32) ? 0 : 0xffffffffL ;
return 0 ;
}
/* called when a remote command received. For now, we
* refuse to execute commands. Send EPERM and ignore.
*/
int
GotCommand( ZModem *info )
{
u_char rbuf[4] ;
/* TODO: add command capability */
rbuf[0] = EPERM ;
rbuf[1] = rbuf[2] = rbuf[3] = 0 ;
return ZXmitHdrHex(ZCOMPL, rbuf, info) ;
}
static int
GotCommandData( register ZModem *info )
{
/* TODO */
return 0 ;
}
/* called when the remote system wants to put something to
* stderr
*/
int
GotStderr( register ZModem *info )
{
info->InputState = Indata ;
info->chrCount = 0 ;
return 0 ;
}
static int
GotStderrData( register ZModem *info )
{
info->buffer[info->chrCount] = '\0' ;
ZStatus(RemoteMessage, info->chrCount, (char *)info->buffer) ;
return 0 ;
}
/* Protocol failure: An unexpected packet arrived. This could
* be from many sources, such as old pipelined info finally arriving
* or a serial line with echo enabled. Report it and ignore it.
*/
int
ZPF( ZModem *info )
{
info->waitflag = 1 ; /* pause any in-progress transmission */
ZStatus(ProtocolErr, info->hdrData[0], NULL) ;
return 0 ;
}
int
AnswerChallenge( register ZModem *info )
{
return ZXmitHdrHex(ZACK, info->hdrData+1, info) ;
}
int
GotAbort( register ZModem *info )
{
ZStatus(RmtCancel, 0, NULL) ;
return ZXmitHdrHex(ZFIN, zeros, info) ;
}

709
deps/Xmodem/zmodem.h vendored Normal file
View File

@@ -0,0 +1,709 @@
/* $Id: zmodem.h,v 1.2 2001/10/25 23:56:29 efalk Exp $ */
#ifndef ZMODEM_H
#define ZMODEM_H
/* Master header file for Zmodem protocol driver routines */
#if 0
These routines are intended to be incorportated into other programs,
and do not constitute a zmodem program by themselves, although a
demo zmodem program that uses these routines has been included.
All information pertaining to a transfer session is kept in a data
structure defined by the caller. This makes it possible for the
caller to drive multiple simultaneous sessions.
Caller provides I/O, timing and query routines. Caller remains
in control at all times. Typical use is to call these routines
from a select(2) loop.
Overview:
Transmit files:
1 Init ZModem structure and open communications channel.
2 Call ZmodemTInit() to begin protocol.
3 Read characters from remote end and pass them to
ZmodemRcv() until ZmodemRcv() returns ZmDone or an error.
4 Call ZmodemTFile() to begin transfer of a file.
5 Read characters from remote end and pass them to
ZmodemRcv() until ZmodemRcv() returns ZmDone or an error.
6 repeat steps 4&5 for all files.
7 Call ZmodemTFinish() to indicate that all files have been
transfered.
8 Read characters from remote end and pass them to
ZmodemRcv() until ZmodemRcv() returns ZmDone or an error.
Receive files:
1 Init ZModem structure and open communications channel.
2 Call ZmodemRInit() to begin protocol.
3 Read characters from remote end and pass them to
ZmodemRcv() until ZmodemRcv() returns ZmDone or an error.
In detail:
1) Create a ZModem structure as defined below and fill it in.
'ifd', 'ofd' are the file descriptors used for input and output.
The interpretation of ifd and ofd is entirely up to the calling
routines, since the caller will be providing I/O functions.
'zrinitflags' is composed of the flags described below.
They describe the receive channel capabilities
and affect how the protocol will be carried out.
Define these to receive files. When sending files, these
flags will be defined from the remote end.
'zsinitflags' is composed of the flags described below.
They describe the transmit channel capabilities
and affect how the protocol will be carried out.
Define these to send files. When receiving files, these
flags will be defined from the remote end.
'attn': For transmit, this is the optional nul-terminated
attention string to be sent by the receiver to interrupt the
transmission. For example, it might simply contain ^O to flush
the buffers, or it might interrupt the sending program. Caller
needs to handle this interrupt properly and call ZmodemAttention().
For receive, this is the optional nul-terminated attention string
defined at the remote end. Caller needs to provide a function that
can execute this sequence.
'timeout' is read-only, set by the zmodem package. It is the
timeout value in seconds. If this much time passes without
anything being received, caller should call the ZmodemTimeout()
function. Note that timeout may be zero, in which case the
ZTimeout function should be called immediately if no characters
are ready to be received.
'packetsize' is set to the preferred data packet size. Define
this when sending files. Recommended length values are 256
bytes below 2400 bps, 512 at 2400 bps, and 1024 above 4800 bps
or when the data link is known to be relatively error free.
Ignored during receive.
'bufsize' is set to the size of the receive buffer size. Define
this when receiving files. When sending files, this will be
defined at the other end.
'windowsize' is used to prevent network connections from
buffering too many characters during transmit. Setting
'windowsize' to nonzero causes zmodem to request status reports
from the receiver during transmit, and to pause if more than
this many bytes have been sent but not yet acknowledged. Set
to zero to turn off windowing. Ignored during receive.
Other fields are used to track the internal state of the zmodem
driver functions.
Since this is a source package, you are, of course, free to extend
the ZModem structure as you see fit.
2) Define the following functions:
int
ZXmitStr(u_char *str, int len, ZModem *info)
Transmit a buffer. Return 0 on success, ZmErrSys on error.
void
ZIFlush(ZModem *info)
Flush all unread input on receive channel. Do nothing if
this is not possible.
void
ZOFlush(ZModem *info)
Flush all buffered but not-yet-transmitted output
on transmit channel. Do nothing if this is not possible.
int
ZAttn(ZModem *info)
Send attention signal defined in ZModem->attn. Do
nothing if this field is NULL. Otherwise, this field
is a nul-terminated character string to be
transmitted. There are two special characters defined
below: ATTNBRK (0335) indicates that a BREAK signal
should be sent, and ATTNPSE (0336) represents a
1-second pause.
void
ZFlowControl(int onoff, ZModem *info)
Turn flow control on or off depending on the onoff flag.
void
ZStatus(int type, int value, char *status)
Called to provide status information. Ignore or display
at your option. Status string is not static, so copy
it if you need it beyond this call. Type is defined
below under "ZStatus() types".
FILE *
ZOpenFile(char *name, u_long crc, ZModem *info)
Called when receiving files, this function decides
whether or not to accept the specified file, and
if so, opens it for writing and returns the stdio
file handle. If this function decides not to accept
the file, or cannot open the file, it returns NULL
and the remote sender is told to skip this file.
info->f0-f3 are the transfer flags, described below under
"ZFILE transfer flags". These describe the type of
transfer desired (binary/ascii), and conditions for the
transfer, such as 'transfer if source newer or longer'.
info->len is the length of the file in bytes. info->date is
the last modification date of the file, in seconds since
1-jan-1970. info->mode is the unix file mode + 01000000, or
zero if not known. info->filesRem and info->bytesRem are the
number of files and bytes remaining to be transferred
if known, zero otherwise. 'crc' is the file crc-32 value.
This is only provided if F1 contains ZMCRC.
int
ZWriteFile(u_char *buffer, int len, FILE *file, ZModem *info)
Write a buffer of data to the file. Normally, you would
simply call fwrite(buffer, 1, len, file), but you may
want to translate line endings, etc. File transfer
flags are available as info->f0,f1,f2,f3.
Return 0 on success, ZmErrSys on failure, with errno
describing the failure.
int
ZCloseFile(ZModem *info)
Close file after successful completion. File modification
date and modes should be set at this time.
void
ZIdleStr(u_char *buffer, int len, ZModem *info)
Called to pass text that is received out-of-protocol.
This function may ignore or display this text at your
option.
3) Open the communications channel.
If possible, this should be a full-duplex channel with full
8-bit transmission. Hardware flow control and/or XON/XOFF
flow control should be enabled.
4) Call these routines:
All functions return 0 on success, nonzero on failure. See
"error code definitions", below.
Send:
int
ZmodemTInit(ZModem *info)
Begin a Zmodem transmit session.
int
ZmodemRcv(u_char *buffer, int len, ZModem *info)
Call whenever characters are received. If this function
returns ZmDone, previous function has completed successfully,
either call ZmodemTFile() to start next file, or call
ZmodemTFinish() to terminate the session.
int
ZmodemTimeout(ZModem *info)
Call whenever the timeout period expires and no
characters have been received.
int
ZmodemAttention(ZModem *info)
Call whenever the attention sequence has been received
from the remote end. It is safe to call this function
from an interrupt handler.
int
ZmodemTFile(char *filename, char *rfilename,
u_char f0,f1,f2,f3, int filesRem, int bytesRem, ZModem *info)
Begin transmitting a file. If filename is not NULL,
then this function will open it. Otherwise, info->file
must point to a stdio stream that is open for input.
It is preferable to provide the filename, so that
Zmodem can transmit file size and other information.
'rfilename' is the filename given to the remote end.
This may be the same as filename, the file part of
filename, or something else alltogether. 'rfilename'
must not be longer than the smallest data packet the
remote end might be willing to receive (about 200
characters). f0-f3 are transfer flags, see "ZCBIN"
below. 'filesRem' and 'bytesRem' are the number of files
and bytes remaining to be transmitted, if known; zero if
not.
If 'filename' cannot be accessed, ZmodemTFile() returns
ZmErrCantOpen. The link is still established, so you
need to either proceed with the next file or call
ZmodemTFinish().
int
ZmodemTFinish(ZModem *info)
Call after final file transfer has completed successfully.
int
ZmodemAbort(ZModem *info)
Call to abort transfer. Physical connection remains
open until you close it.
Receive:
int
ZmodemRInit(ZModem *info)
Call to get ready to receive first file. This function
will inform the sender that we are ready to receive.
int
ZmodemRcv(u_char *buffer, int len, ZModem *info)
Call whenever characters are received. If this
function returns ZmDone, all file transfers have
completed successfully.
int
ZmodemTimeout(ZModem *info)
Call whenever the timeout period expires and no
characters have been received.
int
ZmodemAbort(ZModem *info)
Call to abort transfer.
Ymodem and Xmodem:
int YmodemTInit(ZModem *info)
int XmodemTInit(ZModem *info)
int YmodemRInit(ZModem *info)
int XmodemRInit(ZModem *info)
Same semantics as ZmodemTInit and ZmodemRInit. It is
not normally necessary to call the Ymodem*Init() functions
as the Zmodem protocol will automatically switch to Ymodem
when needed.
Utility:
u_long
FileCrc(char *name)
Return CRC-32 of file.
5) Return Values:
ZmDone Done. Proceed with next file or ZmodemTFinish
(transmit) or exit (receive).
ZmErrInt Internal error. Link has been closed.
ZmErrSys System error, see errno. Link is closed.
ZmErrNotOpen not used.
ZmFileTooLong not used.
ZmFileCantWrite not used.
ZmErrCantOpen Can not open file, see errno. Link is still open.
ZmErrInitTo Transmitter failed to respond to init req. Link closed.
ZmErrSequence Packet received out of sequence. Link is closed.
ZmErrCancel Cancelled by remote end. Link is closed.
ZmErrRcvTo Remote end timed out during transfer. Link is closed.
ZmErrSndTo Remote end timed out during transfer. Link is closed.
ZmErrCmdTo Remote end timed out during transfer. Link is closed.
Note that "link is closed" means that the remote end is (presumably)
no longer operating. The actual communications channel is not
closed unless you close it. "Link is still open" means that the
remote end is still ready to receive the next file.
#endif
/* PARAMETERS
*
* The following #defines control the behavior of the Zmodem
* package. Note that these may be replaced with variables
* if you like. For example, "#define DoInitRZ" may be replaced
* with "extern int DoInitRz" to use a global variable, or with
* "#define DoInitRZ (info->doInitRz)" to use a variable you
* add to the ZModem structure.
*
* It is assumed that the compiler is good enough to optimize
* "if( 0 )" and "if( 1 )" cases. If not, you may wish to modify
* the source code to use #ifdef instead.
*/
#define DoInitRZ 1 /* send initial "rz\r" when transmitting */
#define AllowCommand 0 /* allow remote end to execute commands */
#define SendSample 1 /* sender can sample reverse channel */
#define SendAttn 1 /* sender can be interrupted with Attn signal */
#define ResponseTime 10 /* reasonable response time for sender to
* respond to requests from receiver */
#define SerialNo 1 /* receiver serial # */
#define MaxNoise 64 /* max "noise" characters before transmission
* pauses */
#define MaxErrs 20 /* Max receive errors before cancel */
#define AlwaysSinit 1 /* always send ZSINIT header, even if not
* needed, this makes protocol more robust */
#define SendOnly 0 /* compiles smaller version for send only */
#define RcvOnly 0 /* compiles smaller version for receive only */
/* constants */
#include <stdio.h>
#include <sys/types.h>
/* Internal State */
typedef enum zmstate {
/* receive */
RStart, /* sent RINIT, waiting for ZFILE or SINIT */
RSinitWait, /* got SINIT, waiting for data */
RFileName, /* got ZFILE, waiting for filename & info */
RCrc, /* got filename, want crc too */
RFile, /* got filename, ready to read */
RData, /* reading data */
RDataErr, /* encountered error, ignoring input */
RFinish, /* sent ZFIN, waiting for 'OO' */
/* transmit */
TStart, /* waiting for INIT frame from other end */
TInit, /* received INIT, sent INIT, waiting for ZACK */
FileWait, /* sent file header, waiting for ZRPOS */
CrcWait, /* sent file crc, waiting for ZRPOS */
Sending, /* sending data subpackets, ready for int */
SendWait, /* waiting for ZACK */
SendDone, /* file finished, need to send EOF */
SendEof, /* sent EOF, waiting for ZACK */
TFinish, /* sent ZFIN, waiting for ZFIN */
/* general */
CommandData, /* waiting for command data */
CommandWait, /* waiting for command to execute */
StderrData, /* waiting for stderr data */
Done,
/* x/ymodem transmit */
YTStart, /* waiting for 'G', 'C' or NAK */
YTFile, /* sent filename, waiting for ACK */
YTDataWait, /* ready to send data, waiting for 'C' */
YTData, /* sent data, waiting for ACK */
YTEOF, /* sent eof, waiting for ACK */
YTFin, /* sent null filename, waiting for ACK */
/* x/ymodem receive */
YRStart, /* sent 'C', waiting for filename */
YRDataWait, /* received filename, waiting for data */
YRData, /* receiving filename or data */
YREOF /* received first EOT, waiting for 2nd */
} ZMState ;
typedef struct {
int ifd ; /* input fd, for use by caller's routines */
int ofd ; /* output fd, for use by caller's routines */
FILE *file ; /* file being transfered */
int zrinitflags ; /* receiver capabilities, see below */
int zsinitflags ; /* sender capabilities, see below */
char *attn ; /* attention string, see below */
int timeout ; /* timeout value, in seconds */
int bufsize ; /* receive buffer size, bytes */
int packetsize ; /* preferred transmit packet size */
int windowsize ; /* max window size */
/* file attributes: read-only */
int filesRem, bytesRem ;
u_char f0,f1,f2,f3 ; /* file flags */
int len,mode,fileType ; /* file flags */
u_long date ; /* file date */
/* From here down, internal to Zmodem package */
ZMState state ; /* protocol internal state */
char *filename ; /* filename */
char *rfilename ; /* remote filename */
int crc32 ; /* use 32-bit crc */
int pktLen ; /* length of this packet */
int DataType ; /* input data type */
int PacketType ; /* type of this packet */
int rcvlen ;
int chrCount ; /* chars received in current header/buffer */
int crcCount ; /* crc characters remaining at end of buffer */
int canCount ; /* how many CAN chars received? */
int noiseCount ; /* how many noise chars received? */
int errorFlush ; /* ignore incoming data because of error */
u_char *buffer ; /* data buffer */
u_long offset ; /* file offset */
u_long lastOffset ; /* last acknowledged offset */
u_long zrposOffset ; /* last offset specified w/zrpos */
int ylen, bufp ; /* len,location of last Ymodem packet */
int fileEof ; /* file eof reached */
int packetCount ; /* # packets received */
int errCount ; /* how many data errors? */
int timeoutCount ; /* how many times timed out? */
int windowCount ; /* how much data sent in current window */
int atSign ; /* last char was '@' */
int lastCR ; /* last char was CR */
int escCtrl ; /* other end requests ctrl chars be escaped */
int escHibit ; /* other end requests hi bit be escaped */
int escape ; /* next character is escaped */
int interrupt ; /* received attention signal */
int waitflag ; /* next send should wait */
/* parser state */
enum {Idle, Padding, Inhdr, Indata, Finish, Ysend, Yrcv} InputState ;
enum {XMODEM, YMODEM, ZMODEM} Protocol ;
u_char hdrData[9] ; /* header type and data */
u_char fileFlags[4] ; /* file xfer flags */
u_long crc ; /* crc of incoming header/data */
enum {Full, StrWindow, SlidingWindow, Segmented} Streaming ;
} ZModem ;
/* ZRINIT flags. Describe receiver capabilities */
#define CANFDX 1 /* Rx is Full duplex */
#define CANOVIO 2 /* Rx can overlap I/O */
#define CANBRK 4 /* Rx can send a break */
#define CANCRY 010 /* Rx can decrypt */
#define CANLZW 020 /* Rx can uncompress */
#define CANFC32 040 /* Rx can use 32-bit crc */
#define ESCCTL 0100 /* Rx needs control chars escaped */
#define ESC8 0200 /* Rx needs 8th bit escaped. */
/* ZSINIT flags. Describe sender capabilities */
#define TESCCTL 0100 /* Tx needs control chars escaped */
#define TESC8 0200 /* Tx needs 8th bit escaped. */
/* ZFILE transfer flags */
/* F0 */
#define ZCBIN 1 /* binary transfer */
#define ZCNL 2 /* convert NL to local eol convention */
#define ZCRESUM 3 /* resume interrupted file xfer, or append to a
growing file. */
/* F1 */
#define ZMNEWL 1 /* transfer if source newer or longer */
#define ZMCRC 2 /* transfer if different CRC or length */
#define ZMAPND 3 /* append to existing file, if any */
#define ZMCLOB 4 /* replace existing file */
#define ZMNEW 5 /* transfer if source is newer */
#define ZMDIFF 6 /* transfer if dates or lengths different */
#define ZMPROT 7 /* protect: transfer only if dest doesn't exist */
#define ZMCHNG 8 /* change filename if destination exists */
#define ZMMASK 037 /* mask for above. */
#define ZMSKNOLOC 0200 /* skip if not present at Rx end */
/* F2 */
#define ZTLZW 1 /* lzw compression */
#define ZTRLE 3 /* run-length encoding */
/* F3 */
#define ZCANVHDR 1 /* variable headers ok */
#define ZRWOVR 4 /* byte position for receive window override/256 */
#define ZXSPARS 64 /* encoding for sparse file ops. */
/* ATTN string special characters. All other characters sent verbose */
#define ATTNBRK '\335' /* send break signal */
#define ATTNPSE '\336' /* pause for one second */
/* ZStatus() types */
#define RcvByteCount 0 /* value is # bytes received */
#define SndByteCount 1 /* value is # bytes sent */
#define RcvTimeout 2 /* receiver did not respond, aborting */
#define SndTimeout 3 /* value is # of consecutive send timeouts */
#define RmtCancel 4 /* remote end has cancelled */
#define ProtocolErr 5 /* protocol error has occurred, val=hdr */
#define RemoteMessage 6 /* message from remote end */
#define DataErr 7 /* data error, val=error count */
#define FileErr 8 /* error writing file, val=errno */
#define FileBegin 9 /* file transfer begins, str=name */
#define FileEnd 10 /* file transfer ends, str=name */
#define FileSkip 11 /* file being skipped, str=name */
/* error code definitions [O] means link still open */
#define ZmDone -1 /* done */
#define ZmErrInt -2 /* internal error */
#define ZmErrSys -3 /* system error, see errno */
#define ZmErrNotOpen -4 /* communication channel not open */
#define ZmErrCantOpen -5 /* can't open file, see errno [O] */
#define ZmFileTooLong -6 /* remote filename too long [O] */
#define ZmFileCantWrite -7 /* could not write file, see errno */
#define ZmDataErr -8 /* too many data errors */
#define ZmErrInitTo -10 /* transmitter failed to respond to init req. */
#define ZmErrSequence -11 /* packet received out of sequence */
#define ZmErrCancel -12 /* cancelled by remote end */
#define ZmErrRcvTo -13 /* remote receiver timed out during transfer */
#define ZmErrSndTo -14 /* remote sender timed out during transfer */
#define ZmErrCmdTo -15 /* remote command timed out */
/* zmodem-supplied functions: */
extern int ZmodemTInit(ZModem *info) ;
extern int ZmodemTFile(char *file, char *rmtname,
u_int f0, u_int f1, u_int f2, u_int f3,
int filesRem, int bytesRem, ZModem *info) ;
extern int ZmodemTFinish(ZModem *info) ;
extern int ZmodemAbort(ZModem *info) ;
extern int ZmodemRInit(ZModem *info) ;
extern int ZmodemRcv(u_char *str, int len, ZModem *info) ;
extern int ZmodemTimeout(ZModem *info) ;
extern int ZmodemAttention(ZModem *info) ;
extern int YmodemTInit(ZModem *info) ;
extern int XmodemTInit(ZModem *info) ;
extern int YmodemRInit(ZModem *info) ;
extern int XmodemRInit(ZModem *info) ;
extern u_long FileCrc(char *name) ;
extern char *sname(ZModem *) ;
extern char *sname2(ZMState) ;
#ifdef DEBUG
extern FILE *zmodemlogfile ;
extern void zmodemlog(const char *, ...) ;
#else
#define zmodemlog
#endif
/* caller-supplied functions: */
extern int ZXmitChr(u_char c, ZModem *info) ;
extern int ZXmitStr(u_char *str, int len, ZModem *info) ;
extern void ZIFlush(ZModem *info) ;
extern void ZOFlush(ZModem *info) ;
extern int ZAttn(ZModem *info) ;
extern void ZStatus(int type, int value, char *status) ;
extern FILE *ZOpenFile(char *name, u_long crc, ZModem *info) ;
/* From here on down, internal to Zmodem package */
/* ZModem character definitions */
#define ZDLE 030 /* zmodem escape is CAN */
#define ZPAD '*' /* pad */
#define ZBIN 'A' /* introduces 16-bit crc binary header */
#define ZHEX 'B' /* introduces 16-bit crc hex header */
#define ZBIN32 'C' /* introduces 32-bit crc binary header */
#define ZBINR32 'D' /* introduces RLE packed binary frame w/32-bit crc */
#define ZVBIN 'a' /* alternate ZBIN */
#define ZVHEX 'b' /* alternate ZHEX */
#define ZVBIN32 'c' /* alternate ZBIN32 */
#define ZVBINR32 'd' /* alternate ZBINR32 */
#define ZRESC 0177 /* RLE flag/escape character */
/* ZModem header type codes */
#define ZRQINIT 0 /* request receive init */
#define ZRINIT 1 /* receive init */
#define ZSINIT 2 /* send init sequence, define Attn */
#define ZACK 3 /* ACK */
#define ZFILE 4 /* file name, from sender */
#define ZSKIP 5 /* skip file command, from receiver */
#define ZNAK 6 /* last packet was garbled */
#define ZABORT 7 /* abort */
#define ZFIN 8 /* finish session */
#define ZRPOS 9 /* resume file from this position, from receiver */
#define ZDATA 10 /* data packets to follow, from sender */
#define ZEOF 11 /* end of file, from sender */
#define ZFERR 12 /* fatal i/o error, from receiver */
#define ZCRC 13 /* request for file crc, from receiver */
#define ZCHALLENGE 14 /* "send this number back to me", from receiver */
#define ZCOMPL 15 /* request is complete */
#define ZCAN 16 /* other end cancelled with CAN-CAN-CAN-CAN-CAN */
#define ZFREECNT 17 /* request for free bytes on filesystem */
#define ZCOMMAND 18 /* command, from sending program */
#define ZSTDERR 19 /* output this message to stderr */
/* ZDLE escape sequences */
#define ZCRCE 'h' /* CRC next, frame ends, header follows */
#define ZCRCG 'i' /* CRC next, frame continues nonstop */
#define ZCRCQ 'j' /* CRC next, send ZACK, frame continues nonstop */
#define ZCRCW 'k' /* CRC next, send ZACK, frame ends */
#define ZRUB0 'l' /* translate to 0177 */
#define ZRUB1 'm' /* translate to 0377 */
/* ascii definitions */
#define SOH 1 /* ^A */
#define STX 2 /* ^B */
#define EOT 4 /* ^D */
#define ACK 6 /* ^F */
#define DLE 16 /* ^P */
#define XON 17 /* ^Q */
#define XOFF 19 /* ^S */
#define NAK 21 /* ^U */
#define SYN 22 /* ^V */
#define CAN 24 /* ^X */
extern int ZXmitHdr() ;
extern int ZXmitHdrHex() ;
extern int ZXmitHdrBin() ;
extern int ZXmitHdrBin32() ;
extern u_char *putZdle( u_char *ptr, u_char c, ZModem *info ) ;
extern u_char *ZEnc4() ;
extern u_long ZDec4() ;
/* state table entry. There is one row of the table per
* possible state. Each row is a row of all reasonable
* inputs for this state. The entries are sorted so that
* the most common inputs occur first, to reduce search time
* Unexpected input is reported and ignored, as it might be
* caused by echo or something.
*
* Extra ZRINIT headers are the receiver trying to resync.
*/
typedef struct {
int type ; /* frame type */
int (*func)() ; /* transition function */
int IFlush ; /* flag: flush input first */
int OFlush ; /* flag: flush output first */
ZMState newstate ; /* new state. May be overridden by func */
} StateTable ;
#endif

582
deps/Xmodem/zmodemdump.c vendored Normal file
View File

@@ -0,0 +1,582 @@
#ifndef lint
static const char rcsid[] = "$Id: zmodemdump.c,v 1.2 2001/10/25 23:56:29 efalk Exp $" ;
#endif
/* variation on serialmon companion program serialdump, which
* interprets data as a zmodem dialog
*/
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <time.h>
#include <sys/termios.h>
#include <sys/types.h>
#include <sys/time.h>
#include <assert.h>
#include "crctab.h"
#define MAXBUF 2048
#define MAXLINE 16
#define MAXHBUF 128
#define OLINELEN (MAXLINE*2)
#define CAN 030
#define XON 021
#define ZDLE 030
#define ZPAD '*'
#define ZBIN 'A'
#define ZHEX 'B'
#define ZBIN32 'C'
#define ZBINR32 'D'
#define ZVBIN 'a'
#define ZVHEX 'b'
#define ZVBIN32 'c'
#define ZVBINR32 'd'
#define ZRESC 0177
#define ZRQINIT 0 /* request receive init */
#define ZRINIT 1 /* receive init */
#define ZSINIT 2 /* send init sequence, define Attn */
#define ZACK 3 /* ACK */
#define ZFILE 4 /* file name, from sender */
#define ZSKIP 5 /* skip file command, from receiver */
#define ZNAK 6 /* last packet was garbled */
#define ZABORT 7 /* abort */
#define ZFIN 8 /* finish session */
#define ZRPOS 9 /* resume file from this position, from receiver */
#define ZDATA 10 /* data packets to follow, from sender */
#define ZEOF 11 /* end of file, from sender */
#define ZFERR 12 /* fatal i/o error, from receiver */
#define ZCRC 13 /* request for file crc, from receiver */
#define ZCHALLENGE 14 /* "send this number back to me", from receiver */
#define ZCOMPL 15 /* request is complete */
#define ZCAN 16 /* other end cancelled with CAN-CAN-CAN-CAN-CAN */
#define ZFREECNT 17 /* request for free bytes on filesystem */
#define ZCOMMAND 18 /* command, from sending program */
#define ZSTDERR 19 /* output this message to stderr */
#define ZCRCE 'h'
#define ZCRCG 'i'
#define ZCRCQ 'j'
#define ZCRCW 'k'
#define ZRUB0 'l'
#define ZRUB1 'm'
typedef enum {Idle, Padding, HexHeader, Header16, Header32,
InData, InCrc} ZState ;
typedef struct {
ZState state ;
int headertype ;
int data[4] ;
int crcBytes[4] ;
int count ;
int zdlePend ; /* ZDLE received */
int crcCmd ;
int crclen ;
u_long crc ;
} Zinfo ;
u_char buffer[MAXBUF] ;
u_char line[MAXLINE] ;
u_char hbuffer[MAXHBUF] ;
int linecnt = 0 ;
int hbufcnt = 0 ;
main( int argc, char **argv )
{
int i,j ;
int len ;
int which ;
struct timeval timestamp, oldtime ;
struct tm *tm ;
Zinfo Ainfo, Binfo ;
printf("serial log. 'A' is application, 'B' is serial port\n\n") ;
oldtime.tv_sec = 0 ;
Ainfo.state = Binfo.state = Idle ;
Ainfo.zdlePend = Binfo.zdlePend = 0 ;
while( (i=fread((char *)&which, sizeof(which), 1, stdin)) > 0 )
{
i = fread((char *)&timestamp, sizeof(timestamp), 1, stdin) ;
i = fread((char *)&len, sizeof(len), 1, stdin) ;
if( timestamp.tv_sec != oldtime.tv_sec ||
timestamp.tv_usec != oldtime.tv_usec )
{
if( linecnt > 0 )
dumpLine() ;
tm = localtime(&timestamp.tv_sec) ;
printf("%c: %2d:%2.2d:%2.2d.%2.2d\n", 'A'+which,
tm->tm_hour,tm->tm_min,tm->tm_sec, timestamp.tv_usec/10000 ) ;
oldtime = timestamp ;
}
while( len > 0 )
{
i = MAXBUF ;
if( len < i ) i = len ;
j = fread(buffer, 1, i, stdin) ;
assert(j <= MAXBUF) ;
len -= j ;
parseData(which ? &Binfo : &Ainfo, j) ;
}
while( len > 0 )
{
i = MAXLINE - linecnt ;
if( len < i ) i = len ;
assert(linecnt+i <= MAXLINE) ;
j = fread(line+linecnt, 1, i, stdin) ;
assert(linecnt+j <= MAXLINE) ;
len -= j ;
linecnt += j ;
if( linecnt >= MAXLINE )
dumpLine() ;
}
}
if( linecnt > 0 )
dumpLine() ;
exit(0) ;
}
char
toprintable(char c)
{
c &= 0177 ;
if( c >= 0x20 && c <= 0x7e )
return c ;
else
return '.' ;
}
dumpLine()
{
int i,j ;
if( linecnt <= 0 )
return ;
if( linecnt > MAXLINE ) linecnt = MAXLINE ;
printf(" ") ;
for(i=0; i<linecnt; ++i) {
assert(i <= MAXLINE) ;
printf("%2.2x ", line[i]) ;
}
for(; i<MAXLINE; ++i)
printf(" ") ;
printf("\t|") ;
for(i=0; i<linecnt; ++i) {
assert(i <= MAXLINE) ;
printf("%c",toprintable(line[i])) ;
}
printf("|\n") ;
linecnt = 0 ;
}
static u_char hexHeaderStart[] = {ZPAD,ZPAD,ZDLE,ZHEX} ;
static u_char header16Start[] = {ZPAD,ZDLE,ZBIN} ;
static u_char header32Start[] = {ZPAD,ZDLE,ZBIN32} ;
parseData( Zinfo *info, int len )
{
u_char *ptr, c ;
int idx ;
for(ptr = buffer; --len >= 0; ptr++) {
assert(ptr >= buffer && ptr < buffer+MAXBUF) ;
c = *ptr ;
if( c != XON )
switch( info->state ) {
case Idle:
if( c != ZPAD )
dataChar(c) ;
else {
info->state = Padding ;
info->count = 1 ;
hbuffer[0] = c ;
}
break ;
case Padding:
if( c == ZDLE ) {
info->zdlePend = 1 ;
}
else if( info->zdlePend ) {
info->zdlePend = 0 ;
info->count = 0 ;
switch(c) {
case ZHEX:
info->state = HexHeader ;
info->crclen=2 ;
info->crc = 0 ;
break ;
case ZBIN:
info->state = Header16 ;
info->crclen=2 ;
info->crc = 0 ;
break ;
case ZBIN32:
info->state = Header32 ;
info->crclen=4 ;
info->crc = 0xffffffff ;
break ;
default:
cancelHeader(info) ; break ;
}
}
else if( c == ZPAD )
{
if( info->count < 2 ) {
assert(info->count < MAXHBUF) ;
hbuffer[info->count++] = c ;
}
else
dataChar(c) ;
}
else
cancelHeader(info) ; break ;
break ;
case HexHeader:
if( c == ZDLE && !info->zdlePend ) {
info->zdlePend = 1 ;
break ;
}
if( info->zdlePend ) {
c = zdle(c) ;
info->zdlePend = 0 ;
}
idx = info->count++ ;
assert(idx < MAXHBUF) ;
hbuffer[idx] = c ;
if( info->count >= 16 ) { /* end of header */
info->headertype = hex2(hbuffer+0) ;
info->data[0] = hex2(hbuffer+2) ;
info->data[1] = hex2(hbuffer+4) ;
info->data[2] = hex2(hbuffer+6) ;
info->data[3] = hex2(hbuffer+8) ;
info->crcBytes[0] = hex2(hbuffer+10) ;
info->crcBytes[1] = hex2(hbuffer+12) ;
displayHeader(info) ;
}
break ;
case Header16:
if( c == ZDLE && !info->zdlePend ) {
info->zdlePend = 1 ;
break ;
}
if( info->zdlePend ) {
c = zdle(c) ;
info->zdlePend = 0 ;
}
idx = info->count++ ;
assert(idx < MAXHBUF) ;
hbuffer[idx] = c ;
if( info->count >= 7 ) { /* end of header */
info->headertype = hbuffer[0] ;
info->data[0] = hbuffer[1] ;
info->data[1] = hbuffer[2] ;
info->data[2] = hbuffer[3] ;
info->data[3] = hbuffer[4] ;
info->crcBytes[0] = hbuffer[5] ;
info->crcBytes[1] = hbuffer[6] ;
displayHeader(info) ;
}
break ;
case Header32:
if( c == ZDLE && !info->zdlePend ) {
info->zdlePend = 1 ;
break ;
}
if( info->zdlePend ) {
c = zdle(c) ;
info->zdlePend = 0 ;
}
idx = info->count++ ;
assert(idx < MAXHBUF) ;
hbuffer[idx] = c ;
if( info->count >= 9 ) { /* end of header */
info->headertype = hbuffer[0] ;
info->data[0] = hbuffer[1] ;
info->data[1] = hbuffer[2] ;
info->data[2] = hbuffer[3] ;
info->data[3] = hbuffer[4] ;
info->crcBytes[0] = hbuffer[5] ;
info->crcBytes[1] = hbuffer[6] ;
info->crcBytes[2] = hbuffer[7] ;
info->crcBytes[3] = hbuffer[8] ;
displayHeader(info) ;
}
break ;
case InData:
if( info->zdlePend )
{
info->zdlePend = 0 ;
switch( c ) {
case ZCRCE:
case ZCRCW:
case ZCRCG:
case ZCRCQ:
info->crcCmd = c ;
dumpLine() ;
info->state = InCrc ;
info->count = 0 ;
break ;
default:
c = zdle(c) ;
dataChar(c) ;
break ;
}
}
else if( c == ZDLE )
info->zdlePend = 1 ;
else
dataChar(c) ;
break ;
case InCrc:
if( info->zdlePend ) {
c = zdle(c) ;
info->zdlePend = 0 ;
}
if( c == ZDLE )
info->zdlePend = 1 ;
else
{
dataChar(c) ;
if( ++info->count >= info->crclen )
{
dumpCrc() ;
switch( info->crcCmd ) {
case ZCRCE:
printf(" ZCRCE: end of frame, header follows\n") ;
info->state = Idle ;
break ;
case ZCRCW:
printf(" ZCRCW: end of frame, send ZACK\n") ;
info->state = Idle ;
break ;
case ZCRCG:
printf(" ZCRCG: more data follows:\n") ;
info->state = InData ;
break ;
case ZCRCQ:
printf(" ZCRCQ: send ZACK, more data follows:\n") ;
info->state = InData ;
break ;
}
}
}
break ;
}
}
}
/* handle a character that's not part of the protocol */
dataChar(int c)
{
assert(linecnt < MAXLINE) ;
line[linecnt++] = c ;
if( linecnt >= MAXLINE )
dumpLine() ;
}
/* here if we thought we were in a header, but were wrong */
cancelHeader( Zinfo *info )
{
int i ;
for(i=0; i<info->count; ++i) {
assert(i < MAXHBUF) ;
dataChar(hbuffer[i]) ;
}
info->state = Idle ;
}
/* here to display a full header. CRC's not currently checked */
displayHeader( Zinfo *info )
{
int i ;
u_long crc ;
int h32 = info->state == Header32 ;
static char *names[] = {
"ZRQINIT", "ZRINIT", "ZSINIT", "ZACK", "ZFILE", "ZSKIP",
"ZNAK", "ZABORT", "ZFIN", "ZRPOS", "ZDATA", "ZEOF", "ZFERR",
"ZCRC", "ZCHALLENGE", "ZCOMPL", "ZCAN", "ZFREECNT",
"ZCOMMAND", "ZSTDERR",} ;
dumpLine() ;
printf(" ") ;
switch( info->state ) {
case HexHeader: printf("hex header") ; break ;
case Header16: printf("bin header") ; break ;
case Header32: printf("bin32 header") ; break ;
}
printf(" %d: %s: d=[%x %x %x %x]", info->headertype,
info->headertype <= ZSTDERR ? names[info->headertype] : "BAD HEADER",
info->data[0], info->data[1], info->data[2], info->data[3]) ;
switch( info->state ) {
case HexHeader:
case Header16:
printf(" crc=[%x %x]", info->crcBytes[0], info->crcBytes[1]) ;
break ;
case Header32:
printf(" crc=[%x %x %x %x]",
info->crcBytes[0], info->crcBytes[1],
info->crcBytes[2], info->crcBytes[3]) ;
break ;
}
switch( info->headertype ) {
case ZRQINIT:
case ZRINIT:
case ZACK:
case ZSKIP:
case ZNAK:
case ZABORT:
case ZFIN:
case ZRPOS:
case ZEOF:
case ZFERR:
case ZCRC:
case ZCHALLENGE:
case ZCOMPL:
case ZCAN:
case ZFREECNT:
case ZCOMMAND:
printf("\n") ;
info->state = Idle ;
break ;
case ZSINIT:
case ZFILE:
case ZDATA:
case ZSTDERR:
printf(", data follows:\n") ;
info->state = InData ;
info->count = 0 ;
break ;
}
if( !h32 )
{
crc = 0 ;
crc = updcrc(info->headertype, crc) ;
crc = updcrc(info->data[0], crc) ;
crc = updcrc(info->data[1], crc) ;
crc = updcrc(info->data[2], crc) ;
crc = updcrc(info->data[3], crc) ;
crc = updcrc(info->crcBytes[0], crc) ;
crc = updcrc(info->crcBytes[1], crc) ;
if( crc&0xffff != 0 )
printf(" CRC ERROR\n") ;
}
else
{
crc = 0xffffffff ;
crc = UPDC32(info->headertype, crc) ;
crc = UPDC32(info->data[0], crc) ;
crc = UPDC32(info->data[1], crc) ;
crc = UPDC32(info->data[2], crc) ;
crc = UPDC32(info->data[3], crc) ;
crc = UPDC32(info->crcBytes[0], crc) ;
crc = UPDC32(info->crcBytes[1], crc) ;
crc = UPDC32(info->crcBytes[2], crc) ;
crc = UPDC32(info->crcBytes[3], crc) ;
if( crc != 0xdebb20e3 )
printf(" CRC ERROR\n") ;
}
}
dumpCrc()
{
int i,j ;
if( linecnt <= 0 )
return ;
if( linecnt > MAXLINE ) linecnt = MAXLINE ;
printf(" crc: ") ;
for(i=0; i<linecnt; ++i) {
assert(i < MAXLINE) ;
printf("%2.2x ", line[i]) ;
}
printf("\n") ;
linecnt = 0 ;
}
/* return value of 2 hex digits */
int
hex2(char *chrs)
{
return (hex1(chrs[0]) << 4) + hex1(chrs[1]) ;
}
/* return value of a hex digit */
int
hex1(int chr)
{
chr -= '0' ;
if( chr > 9 )
chr -= 'A'-'0'-10 ;
if( chr > 15 )
chr -= 'a' - 'A' ;
return chr ;
}
/* apply ZDLE to chr */
int
zdle(int chr)
{
switch( chr ) {
case ZRUB0: return 0177 ;
case ZRUB1: return 0377 ;
default:
if( (chr & 0140) == 0100 )
return chr ^ 0100 ;
return -1 ;
}
}

750
deps/Xmodem/zmodemr.c vendored Normal file
View File

@@ -0,0 +1,750 @@
#ifndef lint
static const char rcsid[] = "$Id: zmodemr.c,v 1.1.1.1 2001/03/08 00:01:48 efalk Exp $" ;
#endif
/*
* Copyright (c) 1995 by Edward A. Falk
*/
/**********
*
*
* @@@@@ @ @ @@@ @@@@ @@@@@ @ @ @@@@
* @ @@ @@ @ @ @ @ @ @@ @@ @ @
* @ @ @ @ @ @ @ @ @@@ @ @ @ @@@@
* @ @ @ @ @ @ @ @ @ @ @ @ @ @
* @@@@@ @ @ @ @@@ @@@@ @@@@@ @ @ @ @ @
*
* ZMODEMR - receive side of zmodem protocol
*
* receive side of zmodem protocol
*
* This code is designed to be called from inside a larger
* program, so it is implemented as a state machine where
* practical.
*
* functions:
*
* ZmodemRInit(ZModem *info)
* Initiate a connection
*
* ZmodemRAbort(ZModem *info)
* abort transfer
*
* all functions return 0 on success, 1 on failure
*
*
* Edward A. Falk
*
* January, 1995
*
*
*
**********/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include "zmodem.h"
#include "crctab.h"
extern int errno ;
extern int ZWriteFile(u_char *buffer, int len, FILE *, ZModem *);
extern int ZCloseFile(ZModem *info) ;
extern void ZFlowControl(int onoff, ZModem *info) ;
static u_char zeros[4] = {0,0,0,0} ;
int
ZmodemRInit(ZModem *info)
{
info->packetCount = 0 ;
info->offset = 0 ;
info->errCount = 0 ;
info->escCtrl = info->escHibit = info->atSign = info->escape = 0 ;
info->InputState = Idle ;
info->canCount = info->chrCount = 0 ;
info->filename = NULL ;
info->interrupt = 0 ;
info->waitflag = 0 ;
info->attn = NULL ;
info->file = NULL ;
info->buffer = (u_char *)malloc(8192) ;
info->state = RStart ;
info->timeoutCount = 0 ;
ZIFlush(info) ;
/* Don't send ZRINIT right away, there might be a ZRQINIT in
* the input buffer. Instead, set timeout to zero and return.
* This will allow ZmodemRcv() to check the input stream first.
* If nothing found, a ZRINIT will be sent immediately.
*/
info->timeout = 0 ;
zmodemlog("ZmodemRInit[%s]: flush input, new state = RStart\n",
sname(info)) ;
return 0 ;
}
int
YmodemRInit(ZModem *info)
{
info->errCount = 0 ;
info->InputState = Yrcv ;
info->canCount = info->chrCount = 0 ;
info->noiseCount = 0 ;
info->filename = NULL ;
info->file = NULL ;
if( info->buffer == NULL )
info->buffer = (u_char *)malloc(1024) ;
info->state = YRStart ;
info->packetCount = -1 ;
info->timeoutCount = 0 ;
info->timeout = 10 ;
info->offset = 0 ;
ZIFlush(info) ;
return ZXmitStr((u_char *)"C", 1, info) ;
}
extern int ZPF() ;
extern int Ignore() ;
extern int GotCommand() ;
extern int GotStderr() ;
int SendRinit() ;
static int GotSinit() ;
static int GotFile() ;
static int GotFin() ;
static int GotData() ;
static int GotEof() ;
static int GotFreecnt() ;
static int GotFileCrc() ;
int ResendCrcReq() ;
int ResendRpos() ;
/* sent ZRINIT, waiting for ZSINIT or ZFILE */
StateTable RStartOps[] = {
{ZSINIT,GotSinit,0,1,RSinitWait}, /* SINIT, wait for attn str */
{ZFILE,GotFile,0,0,RFileName}, /* FILE, wait for filename */
{ZRQINIT,SendRinit,0,1,RStart}, /* sender confused, resend */
{ZFIN,GotFin,1,0,RFinish}, /* sender shutting down */
{ZNAK,SendRinit,1,0,RStart}, /* RINIT was bad, resend */
#ifdef TODO
{ZCOMPL,f,1,1,s},
#endif /* TODO */
{ZFREECNT,GotFreecnt,0,0,RStart}, /* sender wants free space */
{ZCOMMAND,GotCommand,0,0,CommandData}, /* sender wants command */
{ZSTDERR,GotStderr,0,0,StderrData}, /* sender wants to send msg */
{99,ZPF,0,0,RStart}, /* anything else is an error */
} ;
StateTable RSinitWaitOps[] = { /* waiting for data */
{99,ZPF,0,0,RSinitWait},
} ;
StateTable RFileNameOps[] = { /* waiting for file name */
{99,ZPF,0,0,RFileName},
} ;
StateTable RCrcOps[] = { /* waiting for CRC */
{ZCRC,GotFileCrc,0,0,RFile}, /* sender sent it */
{ZNAK,ResendCrcReq,0,0,RCrc}, /* ZCRC was bad, resend */
{ZRQINIT,SendRinit,1,1,RStart}, /* sender confused, restart */
{ZFIN,GotFin,1,1,RFinish}, /* sender signing off */
{99,ZPF,0,0,RCrc},
} ;
StateTable RFileOps[] = { /* waiting for ZDATA */
{ZDATA,GotData,0,0,RData}, /* got it */
{ZNAK,ResendRpos,0,0,RFile}, /* ZRPOS was bad, resend */
{ZEOF,GotEof,0,0,RStart}, /* end of file */
{ZRQINIT,SendRinit,1,1,RStart}, /* sender confused, restart */
{ZFILE,ResendRpos,0,0,RFile}, /* ZRPOS was bad, resend */
{ZFIN,GotFin,1,1,RFinish}, /* sender signing off */
{99,ZPF,0,0,RFile},
} ;
/* waiting for data, but a packet could possibly arrive due
* to error recovery or something
*/
StateTable RDataOps[] = {
{ZRQINIT,SendRinit,1,1,RStart}, /* sender confused, restart */
{ZFILE,GotFile,0,1,RFileName}, /* start a new file (??) */
{ZNAK,ResendRpos,1,1,RFile}, /* ZRPOS was bad, resend */
{ZFIN,GotFin,1,1,RFinish}, /* sender signing off */
{ZDATA,GotData,0,1,RData}, /* file data follows */
{ZEOF,GotEof,1,1,RStart}, /* end of file */
{99,ZPF,0,0,RData},
} ;
/* here if we've sent ZFERR or ZABORT. Waiting for ZFIN */
StateTable RFinishOps[] = {
{ZRQINIT,SendRinit,1,1,RStart}, /* sender confused, restart */
{ZFILE,GotFile,1,1,RFileName}, /* start a new file */
{ZNAK,GotFin,1,1,RFinish}, /* resend ZFIN */
{ZFIN,GotFin,1,1,RFinish}, /* sender signing off */
{99,ZPF,0,0,RFinish},
} ;
extern char *hdrnames[] ;
extern int dataSetup() ;
/* RECEIVE-RELATED STUFF BELOW HERE */
/* resend ZRINIT header in response to ZRQINIT or ZNAK header */
int
SendRinit( register ZModem *info )
{
u_char dbuf[4] ;
#ifdef COMMENT
if( info->timeoutCount >= 5 )
/* TODO: switch to Ymodem */
#endif /* COMMENT */
zmodemlog("SendRinit[%s]: send ZRINIT\n", sname(info)) ;
info->timeout = ResponseTime ;
dbuf[0] = info->bufsize&0xff ;
dbuf[1] = (info->bufsize>>8)&0xff ;
dbuf[2] = 0 ;
dbuf[3] = info->zrinitflags ;
return ZXmitHdrHex(ZRINIT, dbuf, info) ;
}
/* received a ZSINIT header in response to ZRINIT */
static int
GotSinit( register ZModem *info )
{
zmodemlog("GotSinit[%s]: call dataSetup\n", sname(info)) ;
info->zsinitflags = info->hdrData[4] ;
info->escCtrl = info->zsinitflags & TESCCTL ;
info->escHibit = info->zsinitflags & TESC8 ;
ZFlowControl(1, info) ;
return dataSetup(info) ;
}
/* received rest of ZSINIT packet */
int
GotSinitData( register ZModem *info, int crcGood )
{
info->InputState = Idle ;
info->chrCount=0 ;
info->state = RStart ;
zmodemlog("GotSinitData[%s]: crcGood=%d\n", sname(info), crcGood) ;
if( !crcGood )
return ZXmitHdrHex(ZNAK, zeros, info) ;
if( info->attn != NULL )
free(info->attn) ;
info->attn = NULL ;
if( info->buffer[0] != '\0' )
info->attn = strdup((char *)info->buffer) ;
return ZXmitHdrHex(ZACK, ZEnc4(SerialNo), info) ;
}
/* got ZFILE. Cache flags and set up to receive filename */
static int
GotFile( register ZModem *info )
{
zmodemlog("GotFile[%s]: call dataSetup\n", sname(info)) ;
info->errCount = 0 ;
info->f0 = info->hdrData[4] ;
info->f1 = info->hdrData[3] ;
info->f2 = info->hdrData[2] ;
info->f3 = info->hdrData[1] ;
return dataSetup(info) ;
}
/* utility: see if ZOpenFile wants this file, and if
* so, request it from sender.
*/
static int
requestFile( register ZModem *info, u_long crc )
{
info->file = ZOpenFile((char *)info->buffer, crc, info) ;
if( info->file == NULL ) {
zmodemlog("requestFile[%s]: send ZSKIP\n", sname(info)) ;
info->state = RStart ;
ZStatus(FileSkip, 0, info->filename) ;
return ZXmitHdrHex(ZSKIP, zeros, info) ;
}
else {
zmodemlog("requestFile[%s]: send ZRPOS(%ld)\n",
sname(info), info->offset) ;
info->offset = info->f0 == ZCRESUM ? ftell(info->file) : 0 ;
info->state = RFile ;
ZStatus(FileBegin, 0, info->filename) ;
return ZXmitHdrHex(ZRPOS, ZEnc4(info->offset), info) ;
}
}
/* parse filename info. */
static void
parseFileName( register ZModem *info, char *fileinfo )
{
char *ptr ;
int serial=0 ;
info->len = info->mode = info->filesRem =
info->bytesRem = info->fileType = 0 ;
ptr = fileinfo + strlen(fileinfo) + 1 ;
if( info->filename != NULL )
free(info->filename) ;
info->filename = strdup(fileinfo) ;
sscanf(ptr, "%d %lo %o %o %d %d %d", &info->len, &info->date,
&info->mode, &serial, &info->filesRem, &info->bytesRem,
&info->fileType) ;
}
/* got filename. Parse arguments from it and execute
* policy function ZOpenFile(), provided by caller
*/
int
GotFileName( register ZModem *info, int crcGood )
{
info->InputState = Idle ;
info->chrCount=0 ;
if( !crcGood ) {
zmodemlog("GotFileName[%s]: bad crc, send ZNAK\n", sname(info)) ;
info->state = RStart ;
return ZXmitHdrHex(ZNAK, zeros, info) ;
}
parseFileName(info, (char *)info->buffer) ;
if( (info->f1 & ZMMASK) == ZMCRC ) {
info->state = RCrc ;
return ZXmitHdrHex(ZCRC, zeros, info) ;
}
zmodemlog("GotFileName[%s]: good crc, call requestFile\n",
sname(info)) ;
info->state = RFile ;
return requestFile(info,0) ;
}
int
ResendCrcReq(ZModem *info)
{
zmodemlog("ResendCrcReq[%s]: send ZCRC\n", sname(info)) ;
return ZXmitHdrHex(ZCRC, zeros, info) ;
}
/* received file CRC, now we're ready to accept or reject */
static int
GotFileCrc( register ZModem *info )
{
zmodemlog("GotFileCrc[%s]: call requestFile\n", sname(info)) ;
return requestFile(info, ZDec4(info->hdrData+1)) ;
}
/* last ZRPOS was bad, resend it */
int
ResendRpos( register ZModem *info )
{
zmodemlog("ResendRpos[%s]: send ZRPOS(%ld)\n",
sname(info), info->offset) ;
return ZXmitHdrHex(ZRPOS, ZEnc4(info->offset), info) ;
}
/* recevied ZDATA header */
static int
GotData( register ZModem *info )
{
int err ;
zmodemlog("GotData[%s]:\n", sname(info)) ;
if( ZDec4(info->hdrData+1) != info->offset ) {
if( info->attn != NULL && (err=ZAttn(info)) != 0 )
return err ;
zmodemlog(" bad, send ZRPOS(%ld)\n", info->offset);
return ZXmitHdrHex(ZRPOS, ZEnc4(info->offset), info) ;
}
/* Let's do it! */
zmodemlog(" call dataSetup\n");
return dataSetup(info) ;
}
/* Utility: flush input, send attn, send specified header */
static int
fileError( register ZModem *info, int type, int data )
{
int err ;
info->InputState = Idle ;
info->chrCount=0 ;
if( info->attn != NULL && (err=ZAttn(info)) != 0 )
return err ;
return ZXmitHdrHex(type, ZEnc4(data), info) ;
}
/* received file data */
int
GotFileData( register ZModem *info, int crcGood )
{
/* OK, now what? Fushing the buffers and executing the
* attn sequence has likely chopped off the input stream
* mid-packet. Now we switch to idle mode and treat all
* incoming stuff like noise until we get a new valid
* packet.
*/
if( !crcGood ) { /* oh bugger, an error. */
zmodemlog(
"GotFileData[%s]: bad crc, send ZRPOS(%ld), new state = RFile\n",
sname(info), info->offset) ;
ZStatus(DataErr, ++info->errCount, NULL) ;
if( info->errCount > MaxErrs ) {
ZmodemAbort(info) ;
return ZmDataErr ;
}
else {
info->state = RFile ;
info->InputState = Idle ;
info->chrCount=0 ;
return fileError(info, ZRPOS, info->offset) ;
}
}
if( ZWriteFile(info->buffer, info->chrCount, info->file, info) )
{
/* RED ALERT! Could not write the file. */
ZStatus(FileErr, errno, NULL) ;
info->state = RFinish ;
info->InputState = Idle ;
info->chrCount=0 ;
return fileError(info, ZFERR, errno) ;
}
zmodemlog("GotFileData[%s]: %ld.%d,",
sname(info), info->offset, info->chrCount) ;
info->offset += info->chrCount ;
ZStatus(RcvByteCount, info->offset, NULL) ;
/* if this was the last data subpacket, leave data mode */
if( info->PacketType == ZCRCE || info->PacketType == ZCRCW ) {
zmodemlog(" ZCRCE|ZCRCW, new state RFile") ;
info->state = RFile ;
info->InputState = Idle ;
info->chrCount=0 ;
}
else {
zmodemlog(" call dataSetup") ;
(void) dataSetup(info) ;
}
if( info->PacketType == ZCRCQ || info->PacketType == ZCRCW ) {
zmodemlog(", send ZACK\n") ;
return ZXmitHdrHex(ZACK, ZEnc4(info->offset), info) ;
}
else
zmodemlog("\n") ;
return 0 ;
}
/* received ZEOF packet, file is now complete */
static int
GotEof( register ZModem *info )
{
zmodemlog("GotEof[%s]: offset=%ld\n", sname(info), info->offset) ;
if( ZDec4(info->hdrData+1) != info->offset ) {
zmodemlog(" bad length, state = RFile\n") ;
info->state = RFile ;
return 0 ; /* it was probably spurious */
}
/* TODO: if we can't close the file, send a ZFERR */
ZCloseFile(info) ; info->file = NULL ;
ZStatus(FileEnd, 0, info->filename) ;
if( info->filename != NULL ) {
free(info->filename) ;
info->filename = NULL ;
}
return SendRinit(info) ;
}
/* got ZFIN, respond in kind */
static int
GotFin( register ZModem *info )
{
zmodemlog("GotFin[%s]: send ZFIN\n", sname(info)) ;
info->InputState = Finish ;
info->chrCount = 0 ;
if( info->filename != NULL )
free(info->filename) ;
return ZXmitHdrHex(ZFIN, zeros, info) ;
}
static int
GotFreecnt( register ZModem *info )
{
/* TODO: how do we find free space on system? */
return ZXmitHdrHex(ZACK, ZEnc4(0xffffffff), info) ;
}
/* YMODEM */
static u_char AckStr[1] = {ACK} ;
static u_char NakStr[1] = {NAK} ;
static u_char CanStr[2] = {CAN,CAN} ;
static int ProcessPacket() ;
static int acceptPacket() ;
static int rejectPacket() ;
static int calcCrc() ;
int
YrcvChar( char c, register ZModem *info )
{
int err ;
if( info->canCount >= 2 ) {
ZStatus(RmtCancel, 0, NULL) ;
return ZmErrCancel ;
}
switch( info->state ) {
case YREOF:
if( c == EOT ) {
ZCloseFile(info) ; info->file = NULL ;
ZStatus(FileEnd, 0, info->filename) ;
if( info->filename != NULL )
free(info->filename) ;
if( (err = acceptPacket(info)) != 0 )
return err ;
info->packetCount = -1 ;
info->offset = 0 ;
info->state = YRStart ;
return ZXmitStr((u_char *)"C", 1, info) ;
}
/* else, drop through */
case YRStart:
case YRDataWait:
switch( c ) {
case SOH:
case STX:
info->pktLen = c == SOH ? (128+4) : (1024+4) ;
info->state = YRData ;
info->chrCount = 0 ;
info->timeout = 1 ;
info->noiseCount = 0 ;
info->crc = 0 ;
break ;
case EOT:
/* ignore first EOT to protect against false eot */
info->state = YREOF ;
return rejectPacket(info) ;
default:
if( ++info->noiseCount > 135 )
return ZXmitStr(NakStr, 1, info) ;
break ;
}
break ;
case YRData:
info->buffer[info->chrCount++] = c ;
if( info->chrCount >= info->pktLen )
return ProcessPacket(info) ;
break ;
default:
break ;
}
return 0 ;
}
int
YrcvTimeout( register ZModem *info )
{
switch( info->state )
{
case YRStart:
if( info->timeoutCount >= 10 ) {
(void) ZXmitStr(CanStr, 2, info) ;
return ZmErrInitTo ;
}
return ZXmitStr((u_char *)"C", 1, info) ;
case YRDataWait:
case YREOF:
case YRData:
if( info->timeoutCount >= 10 ) {
(void) ZXmitStr(CanStr, 2, info) ;
return ZmErrRcvTo ;
}
return ZXmitStr(NakStr, 1, info) ;
default: return 0 ;
}
}
static int
ProcessPacket( register ZModem *info )
{
int idx = (u_char) info->buffer[0] ;
int idxc = (u_char) info->buffer[1] ;
int crc0, crc1 ;
int err ;
info->state = YRDataWait ;
if( idxc != 255 - idx ) {
ZStatus(DataErr, ++info->errCount, NULL) ;
return rejectPacket(info) ;
}
if( idx == (info->packetCount%256) ) /* quietly ignore dup */
return acceptPacket(info) ;
if( idx != (info->packetCount+1)%256 ) { /* out of sequence */
(void) ZXmitStr(CanStr, 2, info) ;
return ZmErrSequence ;
}
crc0 = (u_char)info->buffer[info->pktLen-2] << 8 |
(u_char)info->buffer[info->pktLen-1] ;
crc1 = calcCrc(info->buffer+2, info->pktLen-4) ;
if( crc0 != crc1 ) {
ZStatus(DataErr, ++info->errCount, NULL) ;
return rejectPacket(info) ;
}
++info->packetCount ;
if( info->packetCount == 0 ) /* packet 0 is filename */
{
if( info->buffer[2] == '\0' ) { /* null filename is FIN */
(void) acceptPacket(info) ;
return ZmDone ;
}
parseFileName(info, (char *)info->buffer+2) ;
info->file = ZOpenFile(info->filename, 0, info) ;
if( info->file == NULL ) {
(void) ZXmitStr(CanStr, 2, info) ;
return ZmErrCantOpen ;
}
if( (err = acceptPacket(info)) != 0 )
return err ;
return ZXmitStr((u_char *)"C", 1, info) ;
}
if( ZWriteFile(info->buffer+2, info->pktLen-4, info->file, info) ) {
ZStatus(FileErr, errno, NULL) ;
(void) ZXmitStr(CanStr, 2, info) ;
return ZmErrSys ;
}
info->offset += info->pktLen-4 ;
ZStatus(RcvByteCount, info->offset, NULL) ;
(void) acceptPacket(info) ;
return 0 ;
}
static int
rejectPacket( register ZModem *info )
{
info->timeout = 10 ;
return ZXmitStr(NakStr, 1, info) ;
}
static int
acceptPacket( register ZModem *info )
{
info->state = YRDataWait ;
info->timeout = 10 ;
return ZXmitStr(AckStr, 1, info) ;
}
static int
calcCrc( u_char *str, int len )
{
int crc = 0 ;
while( --len >= 0 )
crc = updcrc(*str++, crc) ;
crc = updcrc(0,crc) ; crc = updcrc(0,crc) ;
return crc & 0xffff ;
}

21
deps/Xmodem/zmodemsys.c vendored Normal file
View File

@@ -0,0 +1,21 @@
/* @(#)zmodemsys.c 1.1 95/06/28 Edward Falk */
#include <unistd.h>
/* small utilities for porting between systems */
#ifndef HAVE_STRDUP
char *
strdup( char *str )
{
char *rval ;
int len = strlen(str) + 1 ;
rval = (char *)malloc(len) ;
strcpy(rval,str) ;
return rval ;
}
#endif

1152
deps/Xmodem/zmodemt.c vendored Normal file

File diff suppressed because it is too large Load Diff

408
deps/Xmodem/zmutil.c vendored Normal file
View File

@@ -0,0 +1,408 @@
#ifndef lint
static const char rcsid[] = "$Id: zmutil.c,v 1.1.1.1 2001/03/08 00:01:48 efalk Exp $" ;
#endif
/*
* Copyright (c) 1995 by Edward A. Falk
*/
/**********
*
*
* @@@@@ @ @ @ @ @@@@@ @@@ @
* @ @@ @@ @ @ @ @ @
* @ @ @ @ @ @ @ @ @
* @ @ @ @ @ @ @ @ @
* @@@@@ @ @ @ @@@ @ @@@ @@@@@
*
* ZMUTIL - utilties used by zmodem protocol.
*
* Routines provided here:
*
*
* int ZXmitHdrHex(type, data, info)
* int type ;
* u_char data[4] ;
* ZModem *info ;
*
* transmit zmodem header in hex.
*
*
* int ZXmitHdrBin(type, data, info)
* int type ;
* u_char data[4] ;
* ZModem *info ;
*
* transmit zmodem header in binary.
*
*
* int ZXmitHdrBin32(type, data, info)
* int type ;
* u_char data[4] ;
* ZModem *info ;
*
* transmit zmodem header in binary with 32-bit crc.
*
*
* int ZXmitHdr(type, format, data, info)
* int type, format ;
* u_char data[4] ;
* ZModem *info ;
*
* transmit zmodem header
*
*
* int ZXmitData(format, data, len, term, info)
* int format, len ;
* u_char term ;
* u_char *data ;
* ZModem *info ;
*
* transmit buffer of data.
*
*
* u_long FileCrc(name)
* char *name ;
*
* compute 32-bit crc for a file, returns 0 on not found
*
*
* u_char *ZEnc4(n)
* u_long n ;
*
* convert u_long to 4 bytes.
*
* u_long ZDec4(buf)
* u_char buf[4] ;
*
* convert 4 bytes to u_long
*
*
*
* Edward A. Falk
*
* January, 1995
*
*
*
**********/
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include <sys/time.h>
#include "zmodem.h"
#include "crctab.h"
static char hexChars[] = "0123456789abcdef" ;
extern char *hdrnames[] ;
FILE *zmodemlogfile = NULL ;
/* put a number as two hex digits */
static u_char *
putHex( u_char *ptr, u_char c )
{
*ptr++ = hexChars[(c>>4)&0xf] ;
*ptr++ = hexChars[c&0xf] ;
return ptr ;
}
/* put a number with ZDLE escape if needed */
u_char *
putZdle( register u_char *ptr, register u_char c, register ZModem *info )
{
register u_char c2 = c & 0177 ;
if( c == ZDLE || c2 == 020 || c2 == 021 || c2 == 023 ||
c2 == 0177 || (c2 == 015 && info->atSign) ||
#ifdef COMMENT
c2 == 035 || (c2 == '~' && info->lastCR) ||
#endif /* COMMENT */
c2 == 035 ||
(c2 < 040 && info->escCtrl) )
{
*ptr++ = ZDLE ;
if( c == 0177 )
*ptr = ZRUB0 ;
else if( c == 0377 )
*ptr = ZRUB1 ;
else
*ptr = c^0100 ;
}
else
*ptr = c ;
info->atSign = c2 == '@' ;
info->lastCR = c2 == '\r' ;
return ++ptr ;
}
int
ZXmitHdrHex( int type, u_char data[4], ZModem *info )
{
u_char buffer[128] ;
register u_char *ptr = buffer ;
register u_int crc ;
int i ;
zmodemlog("sending %s: %2.2x %2.2x %2.2x %2.2x = %lx\n",
hdrnames[type], data[0], data[1], data[2], data[3],
ZDec4(data)) ;
*ptr++ = ZPAD ;
*ptr++ = ZPAD ;
*ptr++ = ZDLE ;
*ptr++ = ZHEX ;
ptr = putHex(ptr, type) ; crc = updcrc(type, 0) ;
for( i=4; --i >= 0; ++data ) {
ptr = putHex(ptr, *data) ;
crc = updcrc(*data, crc) ;
}
crc = updcrc(0,crc) ; crc = updcrc(0,crc) ;
ptr = putHex(ptr, (crc>>8)&0xff) ;
ptr = putHex(ptr, crc&0xff) ;
*ptr++ = '\r' ;
*ptr++ = '\n' ;
if( type != ZACK && type != ZFIN )
*ptr++ = XON ;
return ZXmitStr(buffer, ptr-buffer, info) ;
}
int
ZXmitHdrBin( int type, u_char data[4], register ZModem *info )
{
u_char buffer[128] ;
register u_char *ptr = buffer ;
register u_int crc ;
int len ;
zmodemlog("sending %s: %2.2x %2.2x %2.2x %2.2x = %lx\n",
hdrnames[type], data[0], data[1], data[2], data[3],
ZDec4(data)) ;
*ptr++ = ZPAD ;
*ptr++ = ZDLE ;
*ptr++ = ZBIN ;
ptr = putZdle(ptr, type, info) ; crc = updcrc(type, 0) ;
for( len=4; --len >= 0; ++data ) {
ptr = putZdle(ptr, *data, info) ;
crc = updcrc(*data, crc) ;
}
crc = updcrc(0,crc) ; crc = updcrc(0,crc) ;
ptr = putZdle(ptr, (crc>>8)&0xff, info) ;
ptr = putZdle(ptr, crc&0xff, info) ;
len = ptr-buffer ;
return ZXmitStr(buffer, len, info) ;
}
int
ZXmitHdrBin32( int type, u_char data[4], ZModem *info )
{
u_char buffer[128] ;
register u_char *ptr = buffer ;
register u_long crc ;
int len ;
zmodemlog("sending %s: %2.2x %2.2x %2.2x %2.2x = %lx\n",
hdrnames[type], data[0], data[1], data[2], data[3],
ZDec4(data)) ;
*ptr++ = ZPAD ;
*ptr++ = ZDLE ;
*ptr++ = ZBIN32 ;
ptr = putZdle(ptr, type, info) ; crc = UPDC32(type, 0xffffffffL) ;
for( len=4; --len >= 0; ++data ) {
ptr = putZdle(ptr, *data, info) ;
crc = UPDC32(*data, crc) ;
}
crc = ~crc ;
for(len=4; --len >= 0; crc >>= 8)
ptr = putZdle(ptr, crc&0xff, info) ;
len = ptr-buffer ;
return ZXmitStr(buffer, len, info) ;
}
int
ZXmitHdr( int type, int format, u_char data[4], ZModem *info)
{
if( format == ZBIN && info->crc32 )
format = ZBIN32 ;
switch( format ) {
case ZHEX:
return ZXmitHdrHex(type, data, info) ;
case ZBIN:
return ZXmitHdrBin(type, data, info) ;
case ZBIN32:
return ZXmitHdrBin32(type, data, info) ;
default:
return 0 ;
}
}
/* TODO: if input is not a file, need to keep old data
* for possible retransmission */
int
ZXmitData( int format, int len, u_char term, u_char *data, ZModem *info)
{
register u_char *ptr = info->buffer ;
register u_int crc ;
if( format == ZBIN && info->crc32 )
format = ZBIN32 ;
zmodemlog("ZXmiteData: fmt=%c, len=%d, term=%c\n", format, len, term) ;
crc = (format == ZBIN) ? 0 : 0xffffffff ;
while( --len >= 0 ) {
if( format == ZBIN )
crc = updcrc(*data, crc) ;
else
crc = UPDC32(*data, crc) ;
ptr = putZdle(ptr, *data++, info) ;
}
*ptr++ = ZDLE ;
if( format == ZBIN )
crc = updcrc(term, crc) ;
else
crc = UPDC32(term, crc) ;
*ptr++ = term ;
if( format == ZBIN ) {
crc = updcrc(0,crc) ; crc = updcrc(0,crc) ;
ptr = putZdle(ptr, (crc>>8)&0xff, info) ;
ptr = putZdle(ptr, crc&0xff, info) ;
}
else {
crc = ~crc ;
for(len=4; --len >= 0; crc >>= 8)
ptr = putZdle(ptr, crc&0xff, info) ;
}
return ZXmitStr(info->buffer, ptr-info->buffer, info) ;
}
/* compute 32-bit crc for a file, returns 0 on not found */
u_long
FileCrc( char *name )
{
u_long crc ;
FILE *ifile = fopen(name, "r") ;
int i ;
if( ifile == NULL ) /* shouldn't happen, since we did access(2) */
return 0 ;
crc = 0xffffffff ;
while( (i=fgetc(ifile)) != EOF )
crc = UPDC32(i, crc) ;
fclose(ifile) ;
return ~crc ;
}
u_char *
ZEnc4( u_long n )
{
static u_char buf[4] ;
buf[0] = n&0xff ; n >>= 8 ;
buf[1] = n&0xff ; n >>= 8 ;
buf[2] = n&0xff ; n >>= 8 ;
buf[3] = n&0xff ;
return buf ;
}
u_long
ZDec4( u_char buf[4] )
{
return buf[0] | (buf[1]<<8) | (buf[2]<<16) | (buf[3]<<24) ;
}
char *
sname2(ZMState state)
{
static char *names[] = {
"RStart", "RSinitWait", "RFileName", "RCrc", "RFile", "RData",
"RDataErr", "RFinish", "TStart", "TInit", "FileWait", "CrcWait",
"Sending", "SendWait", "SendDone", "SendEof", "TFinish",
"CommandData", "CommandWait", "StderrData", "Done", "YTStart",
"YTFile", "YTDataWait", "YTData", "YTEOF", "YTFin", "YRStart",
"YRDataWait", "YRData", "YREOF"} ;
return names[(int)state] ;
}
char *
sname(ZModem *info)
{
return sname2(info->state) ;
}
#ifdef DEBUG
void
zmodemlog(const char *fmt, ... )
{
va_list ap;
struct timeval tv ;
struct tm *tm ;
static int do_ts = 1 ;
if( zmodemlogfile == NULL )
return ;
if( do_ts ) {
gettimeofday(&tv, NULL) ;
tm = localtime(&tv.tv_sec) ;
fprintf(zmodemlogfile, "%2.2d:%2.2d:%2.2d.%2.2ld: ",
tm->tm_hour, tm->tm_min, tm->tm_sec,
tv.tv_usec/10000) ;
}
do_ts = strchr(fmt, '\n') != NULL ;
va_start(ap, fmt) ;
vfprintf(zmodemlogfile, fmt, ap) ;
va_end(ap) ;
}
#endif /* DEBUG */

504
deps/jamlib/LICENSE vendored Normal file
View File

@@ -0,0 +1,504 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 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.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
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 and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, 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 library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete 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 distribute a copy of this License along with the
Library.
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 Library or any portion
of it, thus forming a work based on the Library, 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) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
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 Library, 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 Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you 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.
If distribution of 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 satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be 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.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library 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.
9. 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 Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
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 with
this License.
11. 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 Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library 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 Library.
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.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library 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.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser 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 Library
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 Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
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
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "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
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. 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 LIBRARY 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
LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), 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 Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. 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.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; 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.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

29
deps/jamlib/Makefile.linux vendored Normal file
View File

@@ -0,0 +1,29 @@
CC = cc $(CPPFLAGS) $(CFLAGS) -D__LINUX__ $(LDFLAGS) -Wall
AR = ar -ru
RM = rm -f
OBJS = crc32.o mbase.o message.o lastread.o subpack.o structrw.o
jamlib.a : $(OBJS)
$(AR) jamlib.a $(OBJS)
crc32.o: crc32.c jam.h
$(CC) -c crc32.c -o crc32.o
mbase.o: mbase.c jam.h
$(CC) -c mbase.c -o mbase.o
message.o: message.c jam.h
$(CC) -c message.c -o message.o
lastread.o: lastread.c jam.h
$(CC) -c lastread.c -o lastread.o
subpack.o: subpack.c jam.h
$(CC) -c subpack.c -o subpack.o
structrw.o: structrw.c jam.h
$(CC) -c structrw.c -o structrw.o
clean:
$(RM) *.o *.a

29
deps/jamlib/Makefile.minix vendored Normal file
View File

@@ -0,0 +1,29 @@
CC = clang $(CPPFLAGS) $(CFLAGS) -D__LINUX__ $(LDFLAGS) -Wall
AR = ar -ru
RM = rm -f
OBJS = crc32.o mbase.o message.o lastread.o subpack.o structrw.o
jamlib.a : $(OBJS)
$(AR) jamlib.a $(OBJS)
crc32.o: crc32.c jam.h
$(CC) -c crc32.c -o crc32.o
mbase.o: mbase.c jam.h
$(CC) -c mbase.c -o mbase.o
message.o: message.c jam.h
$(CC) -c message.c -o message.o
lastread.o: lastread.c jam.h
$(CC) -c lastread.c -o lastread.o
subpack.o: subpack.c jam.h
$(CC) -c subpack.c -o subpack.o
structrw.o: structrw.c jam.h
$(CC) -c structrw.c -o structrw.o
clean:
$(RM) *.o *.a

30
deps/jamlib/Makefile.os2 vendored Normal file
View File

@@ -0,0 +1,30 @@
CC = gcc -Wall -D__OS2__ -DINCL_DOSPROCESS
AR = ar -ru
RM = del
OBJS = crc32.o mbase.o message.o lastread.o subpack.o structrw.o
jamlib.a: $(OBJS)
$(AR) jamlib.a $(OBJS)
crc32.o: crc32.c jam.h
$(CC) -c crc32.c -o crc32.o
mbase.o: mbase.c jam.h
$(CC) -c mbase.c -o mbase.o
message.o: message.c jam.h
$(CC) -c message.c -o message.o
lastread.o: lastread.c jam.h
$(CC) -c lastread.c -o lastread.o
subpack.o: subpack.c jam.h
$(CC) -c subpack.c -o subpack.o
structrw.o: structrw.c jam.h
$(CC) -c structrw.c -o structrw.o
clean:
$(RM) *.o *.a

29
deps/jamlib/Makefile.win32 vendored Normal file
View File

@@ -0,0 +1,29 @@
CC = gcc -Wall
AR = ar -ru
RM = del
OBJS = crc32.o mbase.o message.o lastread.o subpack.o structrw.o
jamlib.a : $(OBJS)
$(AR) jamlib.a $(OBJS)
crc32.o: crc32.c jam.h
$(CC) -c crc32.c -o crc32.o
mbase.o: mbase.c jam.h
$(CC) -c mbase.c -o mbase.o
message.o: message.c jam.h
$(CC) -c message.c -o message.o
lastread.o: lastread.c jam.h
$(CC) -c lastread.c -o lastread.o
subpack.o: subpack.c jam.h
$(CC) -c subpack.c -o subpack.o
structrw.o: structrw.c jam.h
$(CC) -c structrw.c -o structrw.o
clean:
$(RM) *.o *.a

78
deps/jamlib/crc32.c vendored Normal file
View File

@@ -0,0 +1,78 @@
/*
Crc32 - CRC32-calculation for JAM
Copyright (C) 2000 Johan Billing
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Changes made by Johan Billing 2003-10-22
- Fixed comparison between signed and unsigned variable in JAM_Crc32()
*/
#include "jam.h"
uint32_t crc32tab[] = { /* CRC polynomial 0xedb88320 */
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
/***********************************************************************
**
** JAM_Crc32 - Calculates CRC-32
**
***********************************************************************/
uint32_t JAM_Crc32(char *Buffer_PC, uint32_t Length_I)
{
uint32_t Crc_I;
uint32_t c;
Crc_I=0xffffffff;
for(c=0;c < Length_I; c++)
Crc_I=(Crc_I>>8) ^ crc32tab[(char)Crc_I ^ tolower(Buffer_PC[c])];
return(Crc_I);
}

326
deps/jamlib/jam.h vendored Normal file
View File

@@ -0,0 +1,326 @@
/*
JAMLIB - A JAM subroutine library
Copyright (C) 1999 Bj<42>rn Stenberg
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Changes made by Johan Billing 2000-04-16:
- Added #defines for JAM_NO_MESSAGE and JAM_CORRUPT_MSG
- Added #ifndef linux around typedefs for uint16_t and uint32_t
- Added prototype for JAM_AddEmptyMessage()
Backported changes from JAMLIB 1.4.7 made by Johan Billing 2003-10-26
- Added prototype for JAM_DeleteMessage()
*/
/***********************************************************************
**
** JAM Definitions
**
***********************************************************************/
#ifndef __JAM_H__
#define __JAM_H__
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <stdint.h>
/*
** Error codes
*/
#define JAM_BAD_PARAM 1 /* one or more parameters are wrong */
#define JAM_IO_ERROR 2 /* i/o error. check JAM_Errno() for details */
#define JAM_LOCK_FAILED 3 /* lock could not be set */
#define JAM_NOT_LOCKED 4 /* the message base was not locked before writing */
#define JAM_NO_MEMORY 5 /* out of memory! */
#define JAM_NO_USER 6 /* user not found */
#define JAM_NO_MESSAGE 7 /* message has been deleted */
#define JAM_CORRUPT_MSG 8 /* message header is corrupt */
/*
** CRC definitions
*/
#define JAM_NO_CRC 0xffffffff
/*
** File extensions
*/
#define EXT_HDRFILE ".jhr"
#define EXT_TXTFILE ".jdt"
#define EXT_IDXFILE ".jdx"
#define EXT_LRDFILE ".jlr"
/*
** Revision level and header signature
*/
#define CURRENTREVLEV 1
#define HEADERSIGNATURE "JAM\0"
/*
** Header file information block, stored first in all .JHR files
*/
typedef struct {
char Signature[4]; /* <J><A><M> followed by <NUL> */
uint32_t DateCreated; /* Creation date */
uint32_t ModCounter; /* Last processed counter */
uint32_t ActiveMsgs; /* Number of active (not deleted) msgs */
uint32_t PasswordCRC; /* CRC-32 of password to access */
uint32_t BaseMsgNum; /* Lowest message number in index file */
char RSRVD[1000]; /* Reserved space */
} s_JamBaseHeader;
/*
** Message status bits
*/
#define JAM_MSG_LOCAL 0x00000001L /* Msg created locally */
#define JAM_MSG_INTRANSIT 0x00000002L /* Msg is in-transit */
#define JAM_MSG_PRIVATE 0x00000004L /* Private */
#define JAM_MSG_READ 0x00000008L /* Read by addressee */
#define JAM_MSG_SENT 0x00000010L /* Sent to remote */
#define JAM_MSG_KILLSENT 0x00000020L /* Kill when sent */
#define JAM_MSG_ARCHIVESENT 0x00000040L /* Archive when sent */
#define JAM_MSG_HOLD 0x00000080L /* Hold for pick-up */
#define JAM_MSG_CRASH 0x00000100L /* Crash */
#define JAM_MSG_IMMEDIATE 0x00000200L /* Send Msg now, ignore restrictions */
#define JAM_MSG_DIRECT 0x00000400L /* Send directly to destination */
#define JAM_MSG_GATE 0x00000800L /* Send via gateway */
#define JAM_MSG_FILEREQUEST 0x00001000L /* File request */
#define JAM_MSG_FILEATTACH 0x00002000L /* File(s) attached to Msg */
#define JAM_MSG_TRUNCFILE 0x00004000L /* Truncate file(s) when sent */
#define JAM_MSG_KILLFILE 0x00008000L /* Delete file(s) when sent */
#define JAM_MSG_RECEIPTREQ 0x00010000L /* Return receipt requested */
#define JAM_MSG_CONFIRMREQ 0x00020000L /* Confirmation receipt requested */
#define JAM_MSG_ORPHAN 0x00040000L /* Unknown destination */
#define JAM_MSG_ENCRYPT 0x00080000L /* Msg text is encrypted */
#define JAM_MSG_COMPRESS 0x00100000L /* Msg text is compressed */
#define JAM_MSG_ESCAPED 0x00200000L /* Msg text is seven bit ASCII */
#define JAM_MSG_FPU 0x00400000L /* Force pickup */
#define JAM_MSG_TYPELOCAL 0x00800000L /* Msg is for local use only (no export) */
#define JAM_MSG_TYPEECHO 0x01000000L /* Msg is for conference distribution */
#define JAM_MSG_TYPENET 0x02000000L /* Msg is direct network mail */
#define JAM_MSG_NODISP 0x20000000L /* Msg may not be displayed to user */
#define JAM_MSG_LOCKED 0x40000000L /* Msg is locked, no editing possible */
#define JAM_MSG_DELETED 0x80000000L /* Msg is deleted */
/*
** Message header
*/
typedef struct {
char Signature[4]; /* <J><A><M> followed by <NUL> */
uint16_t Revision; /* CURRENTREVLEV */
uint16_t ReservedWord; /* Reserved */
uint32_t SubfieldLen; /* Length of Subfields */
uint32_t TimesRead; /* Number of times message read */
uint32_t MsgIdCRC; /* CRC-32 of MSGID line */
uint32_t ReplyCRC; /* CRC-32 of REPLY line */
uint32_t ReplyTo; /* This msg is a reply to.. */
uint32_t Reply1st; /* First reply to this msg */
uint32_t ReplyNext; /* Next msg in reply chain */
uint32_t DateWritten; /* When msg was written */
uint32_t DateReceived; /* When msg was received/read */
uint32_t DateProcessed; /* When msg was processed by packer */
uint32_t MsgNum; /* Message number (1-based) */
uint32_t Attribute; /* Msg attribute, see "Status bits" */
uint32_t Attribute2; /* Reserved for future use */
uint32_t TxtOffset; /* Offset of text in text file */
uint32_t TxtLen; /* Length of message text */
uint32_t PasswordCRC; /* CRC-32 of password to access msg */
uint32_t Cost; /* Cost of message */
} s_JamMsgHeader;
/*
** Message header Subfield types
*/
#define JAMSFLD_OADDRESS 0
#define JAMSFLD_DADDRESS 1
#define JAMSFLD_SENDERNAME 2
#define JAMSFLD_RECVRNAME 3
#define JAMSFLD_MSGID 4
#define JAMSFLD_REPLYID 5
#define JAMSFLD_SUBJECT 6
#define JAMSFLD_PID 7
#define JAMSFLD_TRACE 8
#define JAMSFLD_ENCLFILE 9
#define JAMSFLD_ENCLFWALIAS 10
#define JAMSFLD_ENCLFREQ 11
#define JAMSFLD_ENCLFILEWC 12
#define JAMSFLD_ENCLINDFILE 13
#define JAMSFLD_EMBINDAT 1000
#define JAMSFLD_FTSKLUDGE 2000
#define JAMSFLD_SEENBY2D 2001
#define JAMSFLD_PATH2D 2002
#define JAMSFLD_FLAGS 2003
#define JAMSFLD_TZUTCINFO 2004
#define JAMSFLD_UNKNOWN 0xffff
/*
** Message header Subfield
*/
typedef struct {
uint16_t LoID; /* Field ID, 0 - 0xffff */
uint16_t HiID; /* Reserved for future use */
uint32_t DatLen; /* Length of buffer that follows */
char* Buffer; /* DatLen bytes of data */
} s_JamSubfield;
typedef struct {
uint16_t LoID; /* Field ID, 0 - 0xffff */
uint16_t HiID; /* Reserved for future use */
uint32_t DatLen; /* Length of buffer that follows */
} s_JamSaveSubfield;
/*
** Message index record
*/
typedef struct {
uint32_t UserCRC; /* CRC-32 of destination username */
uint32_t HdrOffset; /* Offset of header in .JHR file */
} s_JamIndex;
/*
** Lastread structure, one per user
*/
typedef struct {
uint32_t UserCRC; /* CRC-32 of user name (lowercase) */
uint32_t UserID; /* Unique UserID */
uint32_t LastReadMsg; /* Last read message number */
uint32_t HighReadMsg; /* Highest read message number */
} s_JamLastRead;
/*
** JAMLIB message base handle
*/
typedef struct {
FILE* HdrFile_PS; /* File handle for .JHR file */
FILE* TxtFile_PS; /* File handle for .JDT file */
FILE* IdxFile_PS; /* File handle for .JDX file */
FILE* LrdFile_PS; /* File handle for .JLR file */
int Errno_I; /* last i/o error */
int Locked_I; /* is area locked? */
uint32_t LastUserPos_I; /* last position of lastread record */
uint32_t LastUserId_I; /* userid for the last read lastread record */
} s_JamBase;
/*
** JAMLIB subfield packet
*/
typedef struct {
s_JamSubfield** Fields;
uint32_t NumFields;
uint32_t NumAlloc;
} s_JamSubPacket;
/*
** JAMLIB function declarations
*/
/* mbase.c */
int JAM_OpenMB ( char* Basename_PC,
s_JamBase** NewArea_PPS );
int JAM_CloseMB ( s_JamBase* Area_PS );
int JAM_CreateMB ( char* Basename_PC,
uint32_t BaseMsg_I,
s_JamBase** NewArea_PPS );
int JAM_RemoveMB ( s_JamBase* Area_PS,
char* Basename_PC );
int JAM_LockMB ( s_JamBase* Area_PS,
int Timeout_I );
int JAM_UnlockMB ( s_JamBase* Area_PS );
int JAM_ReadMBHeader ( s_JamBase* Area_PS,
s_JamBaseHeader* Header_PS );
int JAM_WriteMBHeader ( s_JamBase* Area_PS,
s_JamBaseHeader* Header_PS );
int JAM_FindUser ( s_JamBase* Area_PS,
uint32_t UserCrc_I,
uint32_t StartMsg_I,
uint32_t* MsgNo_PI );
int JAM_GetMBSize ( s_JamBase* Area_PS,
uint32_t* Messages_PI );
/* message.c */
int JAM_ReadMsgHeader ( s_JamBase* Area_PS,
uint32_t MsgNo_I,
s_JamMsgHeader* Header_PS,
s_JamSubPacket** SubfieldPack_PPS );
int JAM_ReadMsgText ( s_JamBase* Area_PS,
uint32_t Offset_I,
uint32_t Length_I,
char* Buffer_PC );
int JAM_AddMessage ( s_JamBase* Area_PS,
s_JamMsgHeader* Header_PS,
s_JamSubPacket* SubPack_PS,
char* Text_PC,
uint32_t TextLen_I );
int JAM_AddEmptyMessage ( s_JamBase* Area_PS );
int JAM_DeleteMessage ( s_JamBase* Base_PS,
uint32_t MsgNo_I );
int JAM_ChangeMsgHeader ( s_JamBase* Area_PS,
uint32_t MsgNo_I,
s_JamMsgHeader* Header_PS );
int JAM_ClearMsgHeader ( s_JamMsgHeader* Header_PS );
int JAM_Errno ( s_JamBase* Area_PS );
/* lastread.c */
int JAM_ReadLastRead ( s_JamBase* Area_PS,
uint32_t User_I,
s_JamLastRead* Record_PS );
int JAM_WriteLastRead ( s_JamBase* Area_PS,
uint32_t User_I,
s_JamLastRead* Record_PS );
/* subpacket.c */
s_JamSubPacket* JAM_NewSubPacket ( void );
int JAM_DelSubPacket ( s_JamSubPacket* SubPack_PS );
s_JamSubfield* JAM_GetSubfield ( s_JamSubPacket* SubPack_PS );
s_JamSubfield* JAM_GetSubfield_R ( s_JamSubPacket* SubPack_PS ,
uint32_t* Count_PI);
int JAM_PutSubfield ( s_JamSubPacket* SubPack_PS,
s_JamSubfield* Field_PS );
/* crc32.c */
uint32_t JAM_Crc32 ( char* Buffer_PC, uint32_t Length_I );
#endif

1420
deps/jamlib/jamlib.doc vendored Normal file

File diff suppressed because it is too large Load Diff

174
deps/jamlib/lastread.c vendored Normal file
View File

@@ -0,0 +1,174 @@
/*
JAMLIB - A JAM subroutine library
Copyright (C) 1999 Bj<42>rn Stenberg
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Changes made by Johan Billing 2000-04-16:
- Changed source to use feof() instead of errno == EPASTEOF
- Changed source to use structrw to read and write structures
*/
/***********************************************************************
**
** LASTREAD.C -- Lastread pointer handling
**
** Author: Bj<42>rn Stenberg (bjorn.stenberg@sth.frontec.se)
**
***********************************************************************/
#include <stdio.h>
#include <errno.h>
#include "jam.h"
#include "structrw.h"
/***********************************************************************
**
** File global variables
**
***********************************************************************/
/***********************************************************************
**
** JAM_ReadLastRead - Read LastRead record
**
***********************************************************************/
int JAM_ReadLastRead( s_JamBase* Base_PS,
uint32_t User_I,
s_JamLastRead* Record_PS )
{
s_JamLastRead Record_S;
int Pos_I;
if (!Record_PS)
return JAM_BAD_PARAM;
if ( fseek( Base_PS->LrdFile_PS, 0, SEEK_SET ) ) {
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
for ( Pos_I = 0; ; Pos_I++ ) {
if ( 1 > freadjamlastread(Base_PS->LrdFile_PS,&Record_S) ) {
if ( feof(Base_PS->LrdFile_PS) )
return JAM_NO_USER;
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
if ( Record_S.UserID == User_I ) {
Base_PS->LastUserPos_I = Pos_I;
Base_PS->LastUserId_I = User_I;
*Record_PS = Record_S;
return 0;
}
}
return 0;
}
/***********************************************************************
**
** JAM_WriteLastRead - Write LastRead record
**
***********************************************************************/
int JAM_WriteLastRead( s_JamBase* Base_PS,
uint32_t User_I,
s_JamLastRead* Record_PS )
{
s_JamLastRead Record_S;
int Pos_I;
if (!Record_PS)
return JAM_BAD_PARAM;
/* if the last read is stored */
if ( User_I == Base_PS->LastUserId_I ) {
Pos_I = Base_PS->LastUserPos_I * sizeof( s_JamLastRead );
if ( fseek( Base_PS->LrdFile_PS, Pos_I, SEEK_SET ) ) {
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
/* be safe, check it */
if ( 1 > freadjamlastread(Base_PS->LrdFile_PS,&Record_S) ) {
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
/* is it where we expected it to be? */
if ( User_I == Record_S.UserID ) {
if ( fseek( Base_PS->LrdFile_PS, Pos_I, SEEK_SET ) ) {
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
if ( 1 > fwritejamlastread(Base_PS->LrdFile_PS,Record_PS) ) {
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
fflush(Base_PS -> LrdFile_PS);
return 0;
}
}
/* no last position, or position incorrect */
if ( fseek( Base_PS->LrdFile_PS, 0, SEEK_SET ) ) {
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
for ( Pos_I = 0; ; Pos_I++ ) {
if ( 1 > freadjamlastread(Base_PS->LrdFile_PS,&Record_S) ) {
if ( feof(Base_PS->LrdFile_PS) ) {
/* user not in file, append a new record */
if ( fseek( Base_PS->LrdFile_PS, 0, SEEK_END ) ) {
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
break;
}
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
/* found the user? */
if ( Record_S.UserID == User_I ) {
if ( fseek( Base_PS->LrdFile_PS, Pos_I * sizeof(s_JamLastRead),
SEEK_SET ) ) {
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
break;
}
}
if ( 1 > fwritejamlastread(Base_PS->LrdFile_PS,Record_PS) ) {
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
fflush( Base_PS->LrdFile_PS );
return 0;
}

591
deps/jamlib/mbase.c vendored Normal file
View File

@@ -0,0 +1,591 @@
/*
JAMLIB - A JAM subroutine library
Copyright (C) 1999 Bj<42>rn Stenberg
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Changes made by Johan Billing 2000-04-16:
- Added support for Win32 and Linux
- Changed JAM_OpenMB to open files in binary mode
- Changed source to use feof() instead of errno == EPASTEOF
- Changed source to use structrw to read and write structures
- Fixed broken JAM_FindUser()
- #includes string.h and stdlib.h instead of memory.h
Backported changes from JAMLIB 1.4.7 made by Johan Billing 2003-10-26
- Now uses calloc instead of malloc/memset
- (*NewArea_PPS) will be set to zero even if calloc() failed in
JAM_OpenMB() and JAM_CreateMB()
- JAM_CreateMB() no longer attempts to forever to lock the newly created
messagebase. If the first attempt fails, it will return an error.
- jam_Lock() now sets Base_PS->Errno under Linux
Other changes made by Johan Billing 2003-10-26
- Fixed comparison between signed and unsigned variable in JAM_GetMBSize()
- JAM_CreateMB() would not unlock and close the newly created messagebase
upon failure.
Changes made by Johan Billing 2004-07-10
- Updated the Win32-specific parts of the code to make it compatible with
newer versions of MinGW (tested with 3.1.0-1):
* Now uses Sleep() instead of sleep()
* Changed _LK_UNLOCK to _LK_UNLCK in jam_Lock()
*/
/***********************************************************************
**
** MBASE.C -- Message base handling
**
** Author: Bj<42>rn Stenberg (bjorn.stenberg@sth.frontec.se)
**
***********************************************************************/
#include <stdio.h>
#include <errno.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include "jam.h"
#include "structrw.h"
#if defined( __OS2__ )
#include <os2.h> /* ANSI C does not include file locking :-( */
#endif
#if defined( __WIN32__ )
#include <sys/locking.h>
#include <io.h>
#include <windows.h>
#if !defined( _LK_UNLCK ) && defined ( _LK_UNLOCK )
#define _LK_UNLCK _LK_UNLOCK /* For backwards compatibility */
#endif
#endif
#if defined( __LINUX__ )
#include <sys/file.h>
#include <unistd.h>
#endif
#define OS_ERROR_OFFSET 10000
#if defined( __OS2__ )
#define JAM_Sleep( _x_ ) DosSleep( _x_*1000 )
#endif
#if defined( __WIN32__ )
#define JAM_Sleep(x) Sleep(x*1000)
#endif
#if defined( __LINUX__ )
#define JAM_Sleep(x) sleep(x)
#endif
/*************************************<**********************************
**
** File-global functions
**
***********************************************************************/
int jam_Open( s_JamBase* Base_PS, char* Filename_PC, char* Mode_PC );
int jam_Lock( s_JamBase* Base_PS, int DoLock_I );
/***********************************************************************
**
** JAM_OpenMB - Open message base
**
***********************************************************************/
int JAM_OpenMB( char* Basename_PC, s_JamBase** NewArea_PPS )
{
s_JamBase* Base_PS;
int Status_I;
if ( !NewArea_PPS )
return JAM_BAD_PARAM;
*NewArea_PPS = NULL;
Base_PS = (s_JamBase*) calloc( 1, sizeof( s_JamBase ) );
if (!Base_PS)
return JAM_NO_MEMORY;
*NewArea_PPS = Base_PS;
Status_I = jam_Open( Base_PS, Basename_PC, "r+b" );
if ( Status_I ) {
return Status_I;
}
return 0;
}
/***********************************************************************
**
** JAM_CreateMB - Create a new message base
**
***********************************************************************/
int JAM_CreateMB( char* Basename_PC,
uint32_t BaseMsg_I,
s_JamBase** NewArea_PPS )
{
s_JamBaseHeader Base_S;
int Status_I;
s_JamBase* Base_PS;
if ( !NewArea_PPS || !BaseMsg_I )
return JAM_BAD_PARAM;
*NewArea_PPS = NULL;
Base_PS = (s_JamBase*) calloc( 1, sizeof( s_JamBase ) );
if (!Base_PS)
return JAM_NO_MEMORY;
*NewArea_PPS = Base_PS;
Status_I = jam_Open( Base_PS, Basename_PC, "w+b" );
if ( Status_I )
return Status_I;
Base_S.DateCreated = time(NULL);
Base_S.ModCounter = 0;
Base_S.ActiveMsgs = 0;
Base_S.PasswordCRC = 0xffffffff;
Base_S.BaseMsgNum = BaseMsg_I;
memset( &Base_S.RSRVD, 0, sizeof( Base_S.RSRVD ) );
Status_I = JAM_LockMB( Base_PS, 0 ); /* If the new base cannot be locked directly, something is seriously wrong */
if ( Status_I ) {
JAM_CloseMB(Base_PS);
return Status_I;
}
Status_I = JAM_WriteMBHeader( Base_PS, &Base_S );
if ( Status_I ) {
JAM_UnlockMB( Base_PS );
JAM_CloseMB(Base_PS);
return Status_I;
}
JAM_UnlockMB( Base_PS );
return 0;
}
/***********************************************************************
**
** JAM_CloseMB - Close message base
**
***********************************************************************/
int JAM_CloseMB( s_JamBase* Base_PS )
{
if ( Base_PS->Locked_I ) {
int Status_I = JAM_UnlockMB( Base_PS );
if ( Status_I )
return Status_I;
}
if ( Base_PS->HdrFile_PS ) {
fclose( Base_PS->HdrFile_PS ); Base_PS->HdrFile_PS = NULL;
fclose( Base_PS->TxtFile_PS ); Base_PS->TxtFile_PS = NULL;
fclose( Base_PS->IdxFile_PS ); Base_PS->IdxFile_PS = NULL;
fclose( Base_PS->LrdFile_PS ); Base_PS->LrdFile_PS = NULL;
}
Base_PS->Locked_I = 0;
return 0;
}
/***********************************************************************
**
** JAM_RemoveMB - Remove a message base
**
***********************************************************************/
int JAM_RemoveMB( s_JamBase* Base_PS, char* Basename_PC )
{
char Filename_AC[250];
int Status_AI[4];
/* .JHR file */
sprintf( Filename_AC, "%s%s", Basename_PC, EXT_HDRFILE );
Status_AI[0] = remove( Filename_AC );
if ( Status_AI[0] )
Base_PS->Errno_I = errno;
/* .JDT file */
sprintf( Filename_AC, "%s%s", Basename_PC, EXT_TXTFILE );
Status_AI[1] = remove( Filename_AC );
if ( Status_AI[1] )
Base_PS->Errno_I = errno;
/* .JDX file */
sprintf( Filename_AC, "%s%s", Basename_PC, EXT_IDXFILE );
Status_AI[2] = remove( Filename_AC );
if ( Status_AI[2] )
Base_PS->Errno_I = errno;
/* .JLR file */
sprintf( Filename_AC, "%s%s", Basename_PC, EXT_LRDFILE );
Status_AI[3] = remove( Filename_AC );
if ( Status_AI[3] )
Base_PS->Errno_I = errno;
if (Status_AI[0] || Status_AI[1] || Status_AI[2] || Status_AI[3])
return JAM_IO_ERROR;
return 0;
}
/***********************************************************************
**
** JAM_GetMBSize - Get the number of messages in message base
**
***********************************************************************/
int JAM_GetMBSize( s_JamBase* Base_PS, uint32_t* Messages_PI )
{
long Offset_I;
/* go to end of index file */
if ( fseek( Base_PS->IdxFile_PS, 0, SEEK_END ) ) {
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
Offset_I = ftell( Base_PS->IdxFile_PS );
if ( Offset_I == -1 ) {
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
*Messages_PI = Offset_I / sizeof( s_JamIndex );
return 0;
}
/***********************************************************************
**
** JAM_LockMB - Lock message base
**
***********************************************************************/
int JAM_LockMB( s_JamBase* Base_PS, int Timeout_I )
{
if ( Base_PS->Locked_I )
return 0;
switch ( Timeout_I )
{
/* unlimited timeout */
case -1:
while ( jam_Lock( Base_PS, 1 ) == JAM_LOCK_FAILED )
JAM_Sleep( 1 );
return 0;
/* no timeout */
case 0:
return jam_Lock( Base_PS, 1 );
/* X seconds timeout */
default:
{
time_t Time_I = time(NULL) + Timeout_I;
while ( time(NULL) < Time_I )
{
int Result_I;
Result_I = jam_Lock( Base_PS, 1 );
if ( Result_I == JAM_LOCK_FAILED )
JAM_Sleep( 1 );
else
return Result_I;
}
return JAM_LOCK_FAILED;
}
}
}
/***********************************************************************
**
** JAM_UnlockMB - Flush all writes and unlock message base
**
***********************************************************************/
int JAM_UnlockMB( s_JamBase* Base_PS )
{
fflush( Base_PS->HdrFile_PS );
fflush( Base_PS->TxtFile_PS );
fflush( Base_PS->IdxFile_PS );
fflush( Base_PS->LrdFile_PS );
return jam_Lock( Base_PS, 0 );
}
/***********************************************************************
**
** JAM_ReadMBHeader - Read message base header
**
***********************************************************************/
int JAM_ReadMBHeader( s_JamBase* Base_PS, s_JamBaseHeader* Header_PS )
{
if ( !Header_PS || !Base_PS )
return JAM_BAD_PARAM;
if ( fseek( Base_PS->HdrFile_PS, 0, SEEK_SET ) ) {
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
if ( 1 > freadjambaseheader(Base_PS->HdrFile_PS,Header_PS) ) {
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
return 0;
}
/***********************************************************************
**
** JAM_WriteMBHeader - Write message base header
**
***********************************************************************/
int JAM_WriteMBHeader( s_JamBase* Base_PS, s_JamBaseHeader* Header_PS )
{
if ( !Header_PS || !Base_PS )
return JAM_BAD_PARAM;
if ( !Base_PS->Locked_I )
return JAM_NOT_LOCKED;
if ( fseek( Base_PS->HdrFile_PS, 0, SEEK_SET ) ) {
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
/* ensure header looks right */
memcpy( Header_PS->Signature, HEADERSIGNATURE, 4 );
Header_PS->ModCounter++;
if ( 1 > fwritejambaseheader(Base_PS->HdrFile_PS,Header_PS) ) {
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
fflush( Base_PS->HdrFile_PS );
return 0;
}
/***********************************************************************
**
** JAM_FindUser - Scan scan file for messages to a user
**
***********************************************************************/
int JAM_FindUser( s_JamBase* Base_PS,
uint32_t UserCrc_I,
uint32_t StartMsg_I,
uint32_t* MsgNo_PI )
{
uint32_t MsgNo_I;
/* go to start message */
if ( fseek( Base_PS->IdxFile_PS, StartMsg_I * sizeof( s_JamIndex ),
SEEK_SET ) ) {
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
/* scan file */
for ( MsgNo_I = StartMsg_I; ; MsgNo_I++ ) {
s_JamIndex Index_S;
if ( 1 > freadjamindex(Base_PS->IdxFile_PS,&Index_S) ) {
if ( feof(Base_PS->IdxFile_PS) )
return JAM_NO_USER;
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
if ( Index_S.UserCRC == UserCrc_I )
break;
}
*MsgNo_PI = MsgNo_I;
return 0;
}
/***********************************************************************
**
** jam_Lock - Lock/unlock a message base
**
***********************************************************************/
int jam_Lock( s_JamBase* Base_PS, int DoLock_I )
{
#if defined(__OS2__)
FILELOCK Area_S;
APIRET Status_I;
ULONG Timeout_I = 0;
int Handle_I;
Handle_I = fileno( Base_PS->HdrFile_PS );
if ( Handle_I == -1 ) {
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
Area_S.lOffset = 0;
Area_S.lRange = 1;
if ( DoLock_I )
Status_I = DosSetFileLocks( Handle_I, NULL, &Area_S, Timeout_I, 0 );
else
Status_I = DosSetFileLocks( Handle_I, &Area_S, NULL, Timeout_I, 0 );
if ( Status_I ) {
if ( 232 == Status_I )
return JAM_LOCK_FAILED;
Base_PS->Errno_I = Status_I + OS_ERROR_OFFSET;
return JAM_IO_ERROR;
}
if ( DoLock_I )
Base_PS->Locked_I = 1;
else
Base_PS->Locked_I = 0;
return 0;
#elif defined(__WIN32__)
int Handle_I,Status_I;
fseek(Base_PS->HdrFile_PS,0,SEEK_SET); /* Lock from start of file */
Handle_I = fileno( Base_PS->HdrFile_PS );
if ( Handle_I == -1 ) {
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
if ( DoLock_I )
Status_I = _locking(Handle_I,_LK_NBLCK,1);
else
Status_I = _locking(Handle_I,_LK_UNLCK,1);
if ( Status_I )
return JAM_LOCK_FAILED;
if ( DoLock_I )
Base_PS->Locked_I = 1;
else
Base_PS->Locked_I = 0;
return 0;
#elif defined(__LINUX__)
int Handle_I,Status_I;
struct flock fl;
fseek(Base_PS->HdrFile_PS,0,SEEK_SET); /* Lock from start of file */
Handle_I = fileno( Base_PS->HdrFile_PS );
if ( Handle_I == -1 ) {
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
if(DoLock_I) fl.l_type=F_WRLCK;
else fl.l_type=F_UNLCK;
fl.l_whence=SEEK_SET;
fl.l_start=0;
fl.l_len=1;
fl.l_pid=getpid();
Status_I=fcntl(Handle_I,F_SETLK,&fl);
if ( Status_I ) {
Base_PS->Errno_I = errno;
return JAM_LOCK_FAILED;
}
if ( DoLock_I )
Base_PS->Locked_I = 1;
else
Base_PS->Locked_I = 0;
return 0;
#else
#error Unsupported platform
#endif
}
/***********************************************************************
**
** jam_Open - Open/create message base files
**
***********************************************************************/
int jam_Open( s_JamBase* Base_PS, char* Basename_PC, char* Mode_PC )
{
char Filename_AC[250];
/* .JHR file */
sprintf( Filename_AC, "%s%s", Basename_PC, EXT_HDRFILE );
Base_PS->HdrFile_PS = fopen( Filename_AC, Mode_PC );
if (!Base_PS->HdrFile_PS) {
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
/* .JDT file */
sprintf( Filename_AC, "%s%s", Basename_PC, EXT_TXTFILE );
Base_PS->TxtFile_PS = fopen( Filename_AC, Mode_PC );
if (!Base_PS->TxtFile_PS) {
Base_PS->Errno_I = errno;
fclose( Base_PS->HdrFile_PS ); Base_PS->HdrFile_PS = NULL;
return JAM_IO_ERROR;
}
/* .JDX file */
sprintf( Filename_AC, "%s%s", Basename_PC, EXT_IDXFILE );
Base_PS->IdxFile_PS = fopen( Filename_AC, Mode_PC );
if (!Base_PS->IdxFile_PS) {
Base_PS->Errno_I = errno;
fclose( Base_PS->HdrFile_PS ); Base_PS->HdrFile_PS = NULL;
fclose( Base_PS->TxtFile_PS ); Base_PS->TxtFile_PS = NULL;
return JAM_IO_ERROR;
}
/* .JLR file */
sprintf( Filename_AC, "%s%s", Basename_PC, EXT_LRDFILE );
Base_PS->LrdFile_PS = fopen( Filename_AC, Mode_PC );
if (!Base_PS->LrdFile_PS) {
Base_PS->Errno_I = errno;
fclose( Base_PS->HdrFile_PS ); Base_PS->HdrFile_PS = NULL;
fclose( Base_PS->TxtFile_PS ); Base_PS->TxtFile_PS = NULL;
fclose( Base_PS->IdxFile_PS ); Base_PS->IdxFile_PS = NULL;
return JAM_IO_ERROR;
}
return 0;
}

625
deps/jamlib/message.c vendored Normal file
View File

@@ -0,0 +1,625 @@
/*
JAMLIB - A JAM subroutine library
Copyright (C) 1999 Bj<42>rn Stenberg
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Changes made by Johan Billing 2000-04-16:
- Changed source to use feof() instead of errno == EPASTEOF
- Changed source to use structrw to read and write structures
- Added JAM_AddEmptyMessage()
- Added error messages JAM_NO_MESSAGE and JAM_CORRUPT_MSG for
JAM_ReadMsgHeader()
- #includes stdlib.h instead of malloc.h and memory.h
- Fixed a bug that caused JAM_AddMessage() to fail when trying to
add an empty message to the messagebase under Linux.
Backported changes from JAMLIB 1.4.7 made by Johan Billing 2003-10-26
- Fixed memory leaks that would occur if JAM_ReadMsgHeader() failed
- Added JAM_DeleteMessage()
Other changes made by Johan Billing 2003-10-26
- Fixed comparison between signed and unsigned variable in JAM_AddMessage()
- Improved handling of ActiveMsgs counter. JAM_AddMessage() now only
increases ActiveMsgs if the added message does not have JAM_MSG_DELETED set.
JAM_ChangeMsgHeader() decreases ActiveMsgs if JAM_MSG_DELETED is set and the
message wasn't already deleted. JAM_DeleteMessage() now only decreases
ActiveMsgs if the message wasn't already deleted.
*/
/***********************************************************************
**
** Message.C -- Message handling
**
** Author: Bj<42>rn Stenberg (bjorn.stenberg@sth.frontec.se)
**
***********************************************************************/
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include "jam.h"
#include "structrw.h"
/***********************************************************************
**
** JAM_ReadMsgHeader - Read message header
**
***********************************************************************/
int JAM_ReadMsgHeader( s_JamBase* Base_PS,
uint32_t MsgNo_I,
s_JamMsgHeader* Header_PS,
s_JamSubPacket** SubfieldPack_PPS )
{
s_JamIndex Index_S;
if ( !Base_PS || !Header_PS )
return JAM_BAD_PARAM;
/* find index record */
if ( fseek( Base_PS->IdxFile_PS, MsgNo_I * sizeof( s_JamIndex ), SEEK_SET ) ) {
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
/* read index record */
if ( 1 > freadjamindex(Base_PS->IdxFile_PS,&Index_S) ) {
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
/* message is not there */
if(Index_S.HdrOffset == 0xffffffff && Index_S.UserCRC == 0xffffffff)
{
return JAM_NO_MESSAGE;
}
/* find header */
if ( fseek( Base_PS->HdrFile_PS, Index_S.HdrOffset, SEEK_SET ) ) {
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
/* read header */
if ( 1 > freadjammsgheader(Base_PS->HdrFile_PS,Header_PS) ) {
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
/* are Subfields requested? */
if ( SubfieldPack_PPS && Header_PS->SubfieldLen ) {
s_JamSubPacket* SubPacket_PS;
s_JamSubfield Subfield_S;
char* Buf_PC;
char* Ptr_PC;
char* Roof_PC;
int BufSize_I = Header_PS->SubfieldLen;
Buf_PC = (void*) malloc( BufSize_I );
if ( !Buf_PC )
return JAM_NO_MEMORY;
/* read all subfields */
if ( 1 > fread( Buf_PC, BufSize_I, 1, Base_PS->HdrFile_PS ) ) {
Base_PS->Errno_I = errno;
free (Buf_PC);
return JAM_IO_ERROR;
}
SubPacket_PS = JAM_NewSubPacket();
if ( !SubPacket_PS ) {
free (Buf_PC);
return JAM_NO_MEMORY;
}
Roof_PC = Buf_PC + BufSize_I;
/* cut out the subfields */
for ( Ptr_PC = Buf_PC;
Ptr_PC < Roof_PC;
Ptr_PC += Subfield_S.DatLen + SIZE_JAMSAVESUBFIELD ) {
int Status_I;
getjamsubfield(Ptr_PC,&Subfield_S);
if((char *)Subfield_S.Buffer + Subfield_S.DatLen > Roof_PC) {
JAM_DelSubPacket( SubPacket_PS );
free (Buf_PC);
return JAM_CORRUPT_MSG;
}
Status_I = JAM_PutSubfield( SubPacket_PS, &Subfield_S );
if ( Status_I ) {
JAM_DelSubPacket( SubPacket_PS );
free (Buf_PC);
return Status_I;
}
}
free( Buf_PC );
*SubfieldPack_PPS = SubPacket_PS;
}
else
if ( SubfieldPack_PPS )
/* fields requested but none found */
/* return an empty packet */
*SubfieldPack_PPS = JAM_NewSubPacket();
return 0;
}
/***********************************************************************
**
** JAM_ReadMsgText - Read message text
**
***********************************************************************/
int JAM_ReadMsgText( s_JamBase* Base_PS,
uint32_t Offset_I,
uint32_t Length_I,
char* Buffer_PC )
{
if ( !Base_PS || !Buffer_PC )
return JAM_BAD_PARAM;
if ( !Length_I )
return 0;
if ( fseek( Base_PS->TxtFile_PS, Offset_I, SEEK_SET ) ) {
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
if ( 1 > fread( Buffer_PC, Length_I, 1, Base_PS->TxtFile_PS ) ) {
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
return 0;
}
/***********************************************************************
**
** JAM_ChangeMsgHeader - Change a message header
**
***********************************************************************/
int JAM_ChangeMsgHeader( s_JamBase* Base_PS,
uint32_t MsgNo_I,
s_JamMsgHeader* Header_PS )
{
s_JamBaseHeader BaseHeader_S;
s_JamMsgHeader OldHeader_S;
s_JamIndex Index_S;
int Status_I;
if ( !Base_PS )
return JAM_BAD_PARAM;
if ( !Base_PS->Locked_I )
return JAM_NOT_LOCKED;
/* read message base header */
Status_I = JAM_ReadMBHeader( Base_PS, &BaseHeader_S );
if ( Status_I )
return Status_I;
/* find index record */
if ( fseek( Base_PS->IdxFile_PS, MsgNo_I * sizeof( s_JamIndex ),
SEEK_SET ) ) {
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
/* read index record */
if ( 1 > freadjamindex(Base_PS->IdxFile_PS,&Index_S) ) {
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
/* find header */
if ( fseek( Base_PS->HdrFile_PS, Index_S.HdrOffset, SEEK_SET ) ) {
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
/* read old message header */
if ( 1 > freadjammsgheader( Base_PS->HdrFile_PS, &OldHeader_S ) ) {
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
/* find header */
if ( fseek( Base_PS->HdrFile_PS, Index_S.HdrOffset, SEEK_SET ) ) {
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
/* write header */
if ( 1 > fwritejammsgheader(Base_PS->HdrFile_PS,Header_PS) ) {
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
if( ( Header_PS->Attribute & JAM_MSG_DELETED ) && !(OldHeader_S.Attribute & JAM_MSG_DELETED) ) {
/* message is deleted now but wasn't before */
BaseHeader_S.ActiveMsgs--;
}
Status_I = JAM_WriteMBHeader( Base_PS, &BaseHeader_S );
if ( Status_I )
return Status_I;
return 0;
}
/***********************************************************************
**
** JAM_AddMessage - Add a message to a message base
**
***********************************************************************/
int JAM_AddMessage( s_JamBase* Base_PS,
s_JamMsgHeader* Header_PS,
s_JamSubPacket* SubPack_PS,
char* Text_PC,
uint32_t TextLen_I )
{
s_JamBaseHeader BaseHeader_S;
s_JamIndex Index_S;
long Offset_I;
int Status_I;
uint32_t TotLen_I;
if ( !Base_PS )
return JAM_BAD_PARAM;
if ( !Base_PS->Locked_I )
return JAM_NOT_LOCKED;
/* read message base header */
Status_I = JAM_ReadMBHeader( Base_PS, &BaseHeader_S );
if ( Status_I )
return Status_I;
/*
** Add text if any
*/
Header_PS->TxtOffset = 0;
Header_PS->TxtLen = 0;
if(Text_PC && TextLen_I!=0)
{
/* go to end of text file */
if ( fseek( Base_PS->TxtFile_PS, 0, SEEK_END ) ) {
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
/* store text offset (for header) */
Offset_I = ftell( Base_PS->TxtFile_PS );
if ( Offset_I == -1 ) {
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
Header_PS->TxtOffset = Offset_I;
Header_PS->TxtLen = TextLen_I;
/* write text */
if ( 1 > fwrite( Text_PC, TextLen_I, 1, Base_PS->TxtFile_PS ) ) {
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
}
/*
** Add header
*/
/* go to end of header file */
if ( fseek( Base_PS->HdrFile_PS, 0, SEEK_END ) ) {
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
/* calculate the size of all Subfields */
TotLen_I = 0;
if ( SubPack_PS ) {
s_JamSubfield* Subfield_PS;
for ( Subfield_PS = JAM_GetSubfield( SubPack_PS ); Subfield_PS;
Subfield_PS = JAM_GetSubfield( NULL ) )
TotLen_I += sizeof( s_JamSaveSubfield ) + Subfield_PS->DatLen;
}
Header_PS->SubfieldLen = TotLen_I;
/* go to end of index file */
if ( fseek( Base_PS->IdxFile_PS, 0, SEEK_END ) ) {
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
/* find out new message number (for message header) */
Offset_I = ftell( Base_PS->IdxFile_PS );
if ( Offset_I == -1 ) {
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
/* update header */
Header_PS->MsgNum = Offset_I / sizeof( s_JamIndex ) +
BaseHeader_S.BaseMsgNum;
memcpy( Header_PS->Signature, HEADERSIGNATURE, 4 );
Header_PS->Revision = CURRENTREVLEV;
/* go to end of header file */
if ( fseek( Base_PS->HdrFile_PS, 0, SEEK_END ) ) {
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
/* find out new header offset (for index record) */
Offset_I = ftell( Base_PS->HdrFile_PS );
if ( Offset_I == -1 ) {
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
Index_S.HdrOffset = Offset_I;
/* write new header */
if ( 1 > fwritejammsgheader(Base_PS->HdrFile_PS,Header_PS) ) {
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
/* write Subfields */
if ( SubPack_PS ) {
s_JamSubfield* Subfield_PS;
char User_AC[101];
/* clear username */
User_AC[0] = 0;
for ( Subfield_PS = JAM_GetSubfield( SubPack_PS ); Subfield_PS;
Subfield_PS = JAM_GetSubfield( NULL ) ) {
/* first, save Subfield header */
if ( 1 > fwritejamsavesubfield(Base_PS->HdrFile_PS,(s_JamSaveSubfield *)Subfield_PS) ) {
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
/* then, save Subfield data if any*/
if(Subfield_PS->DatLen) {
if ( 1 > fwrite( Subfield_PS->Buffer, Subfield_PS->DatLen,
1, Base_PS->HdrFile_PS ) ) {
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
}
/* store username for index file */
if ( Subfield_PS->LoID == JAMSFLD_RECVRNAME ) {
memcpy( User_AC, Subfield_PS->Buffer, Subfield_PS->DatLen );
User_AC[ Subfield_PS->DatLen ] = 0;
}
}
/* update index record */
if ( User_AC[0] )
Index_S.UserCRC = JAM_Crc32( User_AC, strlen( User_AC ) );
else
Index_S.UserCRC = JAM_NO_CRC;
}
else
/* update index record */
Index_S.UserCRC = JAM_NO_CRC;
/*
** Add index
*/
/* write index record */
if ( 1 > fwritejamindex(Base_PS->IdxFile_PS,&Index_S) ) {
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
if(!(Header_PS->Attribute & JAM_MSG_DELETED))
BaseHeader_S.ActiveMsgs++; /* Only increase ActiveMsgs if JAM_MSG_DELETED not set */
/* write message base header */
Status_I = JAM_WriteMBHeader( Base_PS, &BaseHeader_S );
if ( Status_I )
return Status_I;
return 0;
}
/***********************************************************************
**
** JAM_AddEmptyMessage - Add a empty message entry to a message base
**
***********************************************************************/
int JAM_AddEmptyMessage( s_JamBase* Base_PS)
{
s_JamIndex Index_S;
if ( !Base_PS )
return JAM_BAD_PARAM;
if ( !Base_PS->Locked_I )
return JAM_NOT_LOCKED;
/* go to end of index file */
if ( fseek( Base_PS->IdxFile_PS, 0, SEEK_END ) ) {
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
/*
** Add index
*/
Index_S.HdrOffset = 0xffffffff;
Index_S.UserCRC = 0xffffffff;
/* write index record */
if ( 1 > fwritejamindex(Base_PS->IdxFile_PS,&Index_S) ) {
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
return 0;
}
/***********************************************************************
**
** JAM_DeleteMessage - Delete message from messagebase
**
***********************************************************************/
int JAM_DeleteMessage( s_JamBase* Base_PS,
uint32_t MsgNo_I )
{
s_JamBaseHeader BaseHeader_S;
s_JamMsgHeader Header_S;
s_JamIndex Index_S;
int Status_I;
uint32_t OldAttribute_I;
if ( !Base_PS )
return JAM_BAD_PARAM;
if ( !Base_PS->Locked_I )
return JAM_NOT_LOCKED;
/* read message base header */
Status_I = JAM_ReadMBHeader( Base_PS, &BaseHeader_S );
if ( Status_I )
return Status_I;
/* find index record */
if ( fseek( Base_PS->IdxFile_PS, MsgNo_I * sizeof( s_JamIndex ), SEEK_SET ) ) {
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
/* read index record */
if ( 1 > freadjamindex( Base_PS->IdxFile_PS, &Index_S ) ) {
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
/* message is not there */
if(Index_S.HdrOffset == 0xffffffff && Index_S.UserCRC == 0xffffffff)
{
return JAM_NO_MESSAGE;
}
/* find header */
if ( fseek( Base_PS->HdrFile_PS, Index_S.HdrOffset, SEEK_SET ) ) {
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
/* read header */
if ( 1 > freadjammsgheader( Base_PS->HdrFile_PS, &Header_S ) ) {
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
OldAttribute_I = Header_S.Attribute;
Header_S.Attribute |= JAM_MSG_DELETED;
/* find header */
if ( fseek( Base_PS->HdrFile_PS, Index_S.HdrOffset, SEEK_SET ) ) {
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
/* write header */
if ( 1 > fwritejammsgheader( Base_PS->HdrFile_PS, &Header_S ) ) {
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
/* find index record */
if ( fseek( Base_PS->IdxFile_PS, MsgNo_I * sizeof( s_JamIndex ), SEEK_SET ) ) {
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
Index_S.HdrOffset = 0xffffffff;
Index_S.UserCRC = 0xffffffff;
/* write index record */
if ( 1 > fwritejamindex(Base_PS->IdxFile_PS,&Index_S) ) {
Base_PS->Errno_I = errno;
return JAM_IO_ERROR;
}
if(!(OldAttribute_I & JAM_MSG_DELETED))
BaseHeader_S.ActiveMsgs--; /* decrease ActiveMsgs if the message wasn't already deleted */
/* write message base header */
Status_I = JAM_WriteMBHeader( Base_PS, &BaseHeader_S );
if ( Status_I )
return Status_I;
return 0;
}
/***********************************************************************
**
** JAM_Errno - Report the latest C library error code
**
***********************************************************************/
int JAM_Errno( s_JamBase* Base_PS )
{
return Base_PS->Errno_I;
}
/***********************************************************************
**
** JAM_ClearMsgHeader - Clear a message header
**
***********************************************************************/
int JAM_ClearMsgHeader( s_JamMsgHeader* Header_PS )
{
if (!Header_PS)
return JAM_BAD_PARAM;
memset( Header_PS, 0, sizeof( s_JamMsgHeader ) );
memcpy( Header_PS->Signature, HEADERSIGNATURE, 4 );
Header_PS->Revision = CURRENTREVLEV;
Header_PS->MsgIdCRC = JAM_NO_CRC;
Header_PS->ReplyCRC = JAM_NO_CRC;
Header_PS->PasswordCRC = JAM_NO_CRC;
return 0;
}

239
deps/jamlib/structrw.c vendored Normal file
View File

@@ -0,0 +1,239 @@
/*
structrw - Platform-independent reading and writing of JAM structs
Copyright (C) 1999 Johan Billing
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Changes made by Johan Billing 2003-10-22
- Added #include <string.h>
*/
#include <stdio.h>
#include <string.h>
#include "jam.h"
#include "structrw.h"
uint16_t jamgetuword(unsigned char *buf,uint32_t offset)
{
return (uint16_t) buf[offset]+
buf[offset+1]*256;
}
void jamputuword(unsigned char *buf,uint32_t offset,uint16_t num)
{
buf[offset]=num%256;
buf[offset+1]=num/256;
}
void jamputuint32_t(unsigned char *buf,uint32_t offset,uint32_t num)
{
buf[offset]=num%256;
buf[offset+1]=(num / 256) % 256;
buf[offset+2]=(num / 256 / 256) % 256;
buf[offset+3]=(num / 256 / 256 / 256) % 256;
}
uint32_t jamgetuint32_t(unsigned char *buf,uint32_t offset)
{
return (uint32_t) buf[offset]+
buf[offset+1]*256+
buf[offset+2]*256*256+
buf[offset+3]*256*256*256;
}
int freadjambaseheader(FILE *fp,s_JamBaseHeader *s_JamBaseHeader)
{
unsigned char buf[SIZE_JAMBASEHEADER];
if(fread(buf,SIZE_JAMBASEHEADER,1,fp) != 1)
return 0;
memcpy(s_JamBaseHeader->Signature,&buf[JAMBASEHEADER_SIGNATURE],4);
s_JamBaseHeader->DateCreated = jamgetuint32_t(buf,JAMBASEHEADER_DATECREATED);
s_JamBaseHeader->ModCounter = jamgetuint32_t(buf,JAMBASEHEADER_MODCOUNTER);
s_JamBaseHeader->ActiveMsgs = jamgetuint32_t(buf,JAMBASEHEADER_ACTIVEMSGS);
s_JamBaseHeader->PasswordCRC = jamgetuint32_t(buf,JAMBASEHEADER_PASSWORDCRC);
s_JamBaseHeader->BaseMsgNum = jamgetuint32_t(buf,JAMBASEHEADER_BASEMSGNUM);
memcpy(s_JamBaseHeader->RSRVD,&buf[JAMBASEHEADER_RSRVD],1000);
return 1;
}
int fwritejambaseheader(FILE *fp,s_JamBaseHeader *s_JamBaseHeader)
{
unsigned char buf[SIZE_JAMBASEHEADER];
memcpy(&buf[JAMBASEHEADER_SIGNATURE],s_JamBaseHeader->Signature,4);
jamputuint32_t(buf,JAMBASEHEADER_DATECREATED, s_JamBaseHeader->DateCreated);
jamputuint32_t(buf,JAMBASEHEADER_MODCOUNTER, s_JamBaseHeader->ModCounter);
jamputuint32_t(buf,JAMBASEHEADER_ACTIVEMSGS, s_JamBaseHeader->ActiveMsgs);
jamputuint32_t(buf,JAMBASEHEADER_PASSWORDCRC, s_JamBaseHeader->PasswordCRC );
jamputuint32_t(buf,JAMBASEHEADER_BASEMSGNUM, s_JamBaseHeader->BaseMsgNum);
memcpy(&buf[JAMBASEHEADER_RSRVD],s_JamBaseHeader->RSRVD,1000);
if(fwrite(buf,SIZE_JAMBASEHEADER,1,fp) != 1)
return 0;
return 1;
}
int freadjammsgheader(FILE *fp,s_JamMsgHeader *s_JamMsgHeader)
{
unsigned char buf[SIZE_JAMMSGHEADER];
if(fread(buf,SIZE_JAMMSGHEADER,1,fp) != 1)
return 0;
memcpy(s_JamMsgHeader->Signature,&buf[JAMMSGHEADER_SIGNATURE],4);
s_JamMsgHeader->Revision = jamgetuword(buf,JAMMSGHEADER_REVISION);
s_JamMsgHeader->ReservedWord = jamgetuword(buf,JAMMSGHEADER_RESERVEDWORD);
s_JamMsgHeader->SubfieldLen = jamgetuint32_t(buf,JAMMSGHEADER_SUBFIELDLEN);
s_JamMsgHeader->TimesRead = jamgetuint32_t(buf,JAMMSGHEADER_TIMESREAD);
s_JamMsgHeader->MsgIdCRC = jamgetuint32_t(buf,JAMMSGHEADER_MSGIDCRC);
s_JamMsgHeader->ReplyCRC = jamgetuint32_t(buf,JAMMSGHEADER_REPLYCRC);
s_JamMsgHeader->ReplyTo = jamgetuint32_t(buf,JAMMSGHEADER_REPLYTO);
s_JamMsgHeader->Reply1st = jamgetuint32_t(buf,JAMMSGHEADER_REPLY1ST);
s_JamMsgHeader->ReplyNext = jamgetuint32_t(buf,JAMMSGHEADER_REPLYNEXT);
s_JamMsgHeader->DateWritten = jamgetuint32_t(buf,JAMMSGHEADER_DATEWRITTEN);
s_JamMsgHeader->DateReceived = jamgetuint32_t(buf,JAMMSGHEADER_DATERECEIVED);
s_JamMsgHeader->DateProcessed = jamgetuint32_t(buf,JAMMSGHEADER_DATEPROCESSED);
s_JamMsgHeader->MsgNum = jamgetuint32_t(buf,JAMMSGHEADER_MSGNUM);
s_JamMsgHeader->Attribute = jamgetuint32_t(buf,JAMMSGHEADER_ATTRIBUTE);
s_JamMsgHeader->Attribute2 = jamgetuint32_t(buf,JAMMSGHEADER_ATTRIBUTE2);
s_JamMsgHeader->TxtOffset = jamgetuint32_t(buf,JAMMSGHEADER_TXTOFFSET);
s_JamMsgHeader->TxtLen = jamgetuint32_t(buf,JAMMSGHEADER_TXTLEN);
s_JamMsgHeader->PasswordCRC = jamgetuint32_t(buf,JAMMSGHEADER_PASSWORDCRC);
s_JamMsgHeader->Cost = jamgetuint32_t(buf,JAMMSGHEADER_COST);
return 1;
}
int fwritejammsgheader(FILE *fp,s_JamMsgHeader *s_JamMsgHeader)
{
unsigned char buf[SIZE_JAMMSGHEADER];
memcpy(&buf[JAMMSGHEADER_SIGNATURE],s_JamMsgHeader->Signature,4);
jamputuword(buf,JAMMSGHEADER_REVISION, s_JamMsgHeader->Revision);
jamputuword(buf,JAMMSGHEADER_RESERVEDWORD, s_JamMsgHeader->ReservedWord);
jamputuint32_t(buf,JAMMSGHEADER_SUBFIELDLEN, s_JamMsgHeader->SubfieldLen);
jamputuint32_t(buf,JAMMSGHEADER_TIMESREAD, s_JamMsgHeader->TimesRead);
jamputuint32_t(buf,JAMMSGHEADER_MSGIDCRC, s_JamMsgHeader->MsgIdCRC);
jamputuint32_t(buf,JAMMSGHEADER_REPLYCRC, s_JamMsgHeader->ReplyCRC );
jamputuint32_t(buf,JAMMSGHEADER_REPLYTO, s_JamMsgHeader->ReplyTo);
jamputuint32_t(buf,JAMMSGHEADER_REPLY1ST, s_JamMsgHeader->Reply1st);
jamputuint32_t(buf,JAMMSGHEADER_REPLYNEXT, s_JamMsgHeader->ReplyNext);
jamputuint32_t(buf,JAMMSGHEADER_DATEWRITTEN, s_JamMsgHeader->DateWritten);
jamputuint32_t(buf,JAMMSGHEADER_DATERECEIVED, s_JamMsgHeader->DateReceived );
jamputuint32_t(buf,JAMMSGHEADER_DATEPROCESSED, s_JamMsgHeader->DateProcessed);
jamputuint32_t(buf,JAMMSGHEADER_MSGNUM, s_JamMsgHeader->MsgNum);
jamputuint32_t(buf,JAMMSGHEADER_ATTRIBUTE, s_JamMsgHeader->Attribute);
jamputuint32_t(buf,JAMMSGHEADER_ATTRIBUTE2, s_JamMsgHeader->Attribute2);
jamputuint32_t(buf,JAMMSGHEADER_TXTOFFSET, s_JamMsgHeader->TxtOffset);
jamputuint32_t(buf,JAMMSGHEADER_TXTLEN, s_JamMsgHeader->TxtLen);
jamputuint32_t(buf,JAMMSGHEADER_PASSWORDCRC, s_JamMsgHeader->PasswordCRC);
jamputuint32_t(buf,JAMMSGHEADER_COST, s_JamMsgHeader->Cost);
if(fwrite(buf,SIZE_JAMMSGHEADER,1,fp) != 1)
return 0;
return 1;
}
int freadjamindex(FILE *fp,s_JamIndex *s_JamIndex)
{
unsigned char buf[SIZE_JAMINDEX];
if(fread(buf,SIZE_JAMINDEX,1,fp) != 1)
return 0;
s_JamIndex->UserCRC = jamgetuint32_t(buf,JAMINDEX_USERCRC);
s_JamIndex->HdrOffset = jamgetuint32_t(buf,JAMINDEX_HDROFFSET);
return 1;
}
int fwritejamindex(FILE *fp,s_JamIndex *s_JamIndex)
{
unsigned char buf[SIZE_JAMINDEX];
jamputuint32_t(buf,JAMINDEX_USERCRC, s_JamIndex->UserCRC);
jamputuint32_t(buf,JAMINDEX_HDROFFSET, s_JamIndex->HdrOffset);
if(fwrite(buf,SIZE_JAMINDEX,1,fp) != 1)
return 0;
return 1;
}
int freadjamlastread(FILE *fp,s_JamLastRead *s_JamLastRead)
{
unsigned char buf[SIZE_JAMLASTREAD];
if(fread(buf,SIZE_JAMLASTREAD,1,fp) != 1)
return 0;
s_JamLastRead->UserCRC = jamgetuint32_t(buf,JAMLASTREAD_USERCRC);
s_JamLastRead->UserID = jamgetuint32_t(buf,JAMLASTREAD_USERID);
s_JamLastRead->LastReadMsg = jamgetuint32_t(buf,JAMLASTREAD_LASTREADMSG);
s_JamLastRead->HighReadMsg = jamgetuint32_t(buf,JAMLASTREAD_HIGHREADMSG);
return 1;
}
int fwritejamlastread(FILE *fp,s_JamLastRead *s_JamLastRead)
{
unsigned char buf[SIZE_JAMLASTREAD];
jamputuint32_t(buf,JAMLASTREAD_USERCRC,s_JamLastRead->UserCRC);
jamputuint32_t(buf,JAMLASTREAD_USERID,s_JamLastRead->UserID);
jamputuint32_t(buf,JAMLASTREAD_LASTREADMSG,s_JamLastRead->LastReadMsg);
jamputuint32_t(buf,JAMLASTREAD_HIGHREADMSG,s_JamLastRead->HighReadMsg);
if(fwrite(buf,SIZE_JAMLASTREAD,1,fp) != 1)
return 0;
return 1;
}
int fwritejamsavesubfield(FILE *fp,s_JamSaveSubfield *s_JamSaveSubfield)
{
unsigned char buf[SIZE_JAMLASTREAD];
jamputuword(buf,JAMSAVESUBFIELD_LOID, s_JamSaveSubfield->LoID);
jamputuword(buf,JAMSAVESUBFIELD_HIID, s_JamSaveSubfield->HiID);
jamputuint32_t(buf,JAMSAVESUBFIELD_DATLEN, s_JamSaveSubfield->DatLen);
if(fwrite(buf,SIZE_JAMSAVESUBFIELD,1,fp) != 1)
return 0;
return 1;
}
void getjamsubfield(unsigned char *buf,s_JamSubfield *Subfield_S)
{
Subfield_S->LoID = jamgetuword(buf,JAMSAVESUBFIELD_LOID);
Subfield_S->HiID = jamgetuword(buf,JAMSAVESUBFIELD_HIID);
Subfield_S->DatLen = jamgetuint32_t(buf,JAMSAVESUBFIELD_DATLEN);
Subfield_S->Buffer = (char *) buf + SIZE_JAMSAVESUBFIELD;
}

86
deps/jamlib/structrw.h vendored Normal file
View File

@@ -0,0 +1,86 @@
/*
structrw - Platform-independent reading and writing of JAM structs
Copyright (C) 1999 Johan Billing
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#define JAMBASEHEADER_SIGNATURE 0
#define JAMBASEHEADER_DATECREATED 4
#define JAMBASEHEADER_MODCOUNTER 8
#define JAMBASEHEADER_ACTIVEMSGS 12
#define JAMBASEHEADER_PASSWORDCRC 16
#define JAMBASEHEADER_BASEMSGNUM 20
#define JAMBASEHEADER_RSRVD 24
#define SIZE_JAMBASEHEADER 1024
#define JAMMSGHEADER_SIGNATURE 0
#define JAMMSGHEADER_REVISION 4
#define JAMMSGHEADER_RESERVEDWORD 6
#define JAMMSGHEADER_SUBFIELDLEN 8
#define JAMMSGHEADER_TIMESREAD 12
#define JAMMSGHEADER_MSGIDCRC 16
#define JAMMSGHEADER_REPLYCRC 20
#define JAMMSGHEADER_REPLYTO 24
#define JAMMSGHEADER_REPLY1ST 28
#define JAMMSGHEADER_REPLYNEXT 32
#define JAMMSGHEADER_DATEWRITTEN 36
#define JAMMSGHEADER_DATERECEIVED 40
#define JAMMSGHEADER_DATEPROCESSED 44
#define JAMMSGHEADER_MSGNUM 48
#define JAMMSGHEADER_ATTRIBUTE 52
#define JAMMSGHEADER_ATTRIBUTE2 56
#define JAMMSGHEADER_TXTOFFSET 60
#define JAMMSGHEADER_TXTLEN 64
#define JAMMSGHEADER_PASSWORDCRC 68
#define JAMMSGHEADER_COST 72
#define SIZE_JAMMSGHEADER 76
#define JAMINDEX_USERCRC 0
#define JAMINDEX_HDROFFSET 4
#define SIZE_JAMINDEX 8
#define JAMLASTREAD_USERCRC 0
#define JAMLASTREAD_USERID 4
#define JAMLASTREAD_LASTREADMSG 8
#define JAMLASTREAD_HIGHREADMSG 12
#define SIZE_JAMLASTREAD 16
#define JAMSAVESUBFIELD_LOID 0
#define JAMSAVESUBFIELD_HIID 2
#define JAMSAVESUBFIELD_DATLEN 4
#define SIZE_JAMSAVESUBFIELD 8
int freadjambaseheader(FILE *fp,s_JamBaseHeader *s_JamBaseHeader);
int fwritejambaseheader(FILE *fp,s_JamBaseHeader *s_JamBaseHeader);
int freadjammsgheader(FILE *fp,s_JamMsgHeader *s_JamMsgHeader);
int fwritejammsgheader(FILE *fp,s_JamMsgHeader *s_JamMsgHeader);
int freadjamindex(FILE *fp,s_JamIndex *s_JamIndex);
int fwritejamindex(FILE *fp,s_JamIndex *s_JamIndex);
int freadjamlastread(FILE *fp,s_JamLastRead *s_JamLastRead);
int fwritejamlastread(FILE *fp,s_JamLastRead *s_JamLastRead);
int fwritejamsavesubfield(FILE *fp,s_JamSaveSubfield *s_JamSaveSubfield);
void getjamsubfield(unsigned char *buf,s_JamSubfield *Subfield_S);

201
deps/jamlib/subpack.c vendored Normal file
View File

@@ -0,0 +1,201 @@
/*
JAMLIB - A JAM subroutine library
Copyright (C) 1999 Bj<42>rn Stenberg
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Changes made by Johan Billing 2000-04-16:
- Fixed broken JAM_GetSubfield()
- #includes stdlib.h instead of malloc.h and memory.h
Changes made by Johan Billing 2000-09-17:
- Added JAM_GetSubfield_R()
Backported changes from JAMLIB 1.4.7 made by Johan Billing 2003-10-22
- JAM_NewSubPacket() and JAM_PutSubField() would give memory leaks under
low memory conditions. Fixed.
Other changes made by Johan Billing 2003-10-22
- Fixed comparison between signed and unsigned variable in
JAM_DelSubPacket() and JAM_GetSubField()
*/
/***********************************************************************
**
** SUBPACKET.C -- Subfield packet handling
**
** Author: Bj<42>rn Stenberg (bjorn.stenberg@sth.frontec.se)
**
***********************************************************************/
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include "jam.h"
/***********************************************************************
**
** JAM_NewSubPacket - Create a new subfield packet
**
***********************************************************************/
s_JamSubPacket* JAM_NewSubPacket( void )
{
s_JamSubPacket* Sub_PS;
/* allocate packet struct */
Sub_PS = (s_JamSubPacket*) malloc( sizeof( s_JamSubPacket ) );
if ( !Sub_PS )
return NULL;
Sub_PS->NumAlloc = 20;
Sub_PS->NumFields = 0;
/* allocate pointer array */
Sub_PS->Fields = (s_JamSubfield**) calloc( Sub_PS->NumAlloc,
sizeof( s_JamSubfield* ) );
if ( !Sub_PS->Fields ) {
free (Sub_PS);
return NULL;
}
return Sub_PS;
}
/***********************************************************************
**
** JAM_DelSubPacket - Free the data associated with a subfield packet
**
***********************************************************************/
int JAM_DelSubPacket( s_JamSubPacket* SubPack_PS )
{
uint32_t i;
if (!SubPack_PS)
return JAM_BAD_PARAM;
for ( i=0; i < SubPack_PS->NumFields; i++ ) {
s_JamSubfield* Field_PS = SubPack_PS->Fields[i];
if ( Field_PS->Buffer )
free( Field_PS->Buffer );
free( Field_PS );
}
free( SubPack_PS->Fields );
free( SubPack_PS );
return 0;
}
/***********************************************************************
**
** JAM_GetSubfield -- Get first/next subfield from a subfield packet
** (not reentrant)
**
***********************************************************************/
s_JamSubfield* JAM_GetSubfield( s_JamSubPacket* SubPack_PS )
{
static s_JamSubPacket* LastPack_PS = NULL;
static uint32_t NextIndex_I = 0;
if ( SubPack_PS ) {
LastPack_PS = SubPack_PS;
NextIndex_I = 0;
}
if ( NextIndex_I < LastPack_PS->NumFields )
return LastPack_PS->Fields[ NextIndex_I++ ];
return NULL;
}
/***********************************************************************
**
** JAM_GetSubfield_R -- Get first/next subfield from a subfield packet
** (reentrant)
**
***********************************************************************/
s_JamSubfield* JAM_GetSubfield_R( s_JamSubPacket* SubPack_PS , uint32_t* Count_PI)
{
if ( *Count_PI < SubPack_PS->NumFields )
return SubPack_PS->Fields[ (*Count_PI)++ ];
return NULL;
}
/***********************************************************************
**
** JAM_PutSubfield -- Add a subfield to a subfield packet
**
***********************************************************************/
int JAM_PutSubfield( s_JamSubPacket* SubPack_PS, s_JamSubfield* Field_PS )
{
s_JamSubfield* NewField_PS;
char* NewBuf_PC;
/* do we have to expand the array? */
if ( SubPack_PS->NumFields == SubPack_PS->NumAlloc ) {
s_JamSubfield** Fields_PPS;
SubPack_PS->NumAlloc *= 2;
Fields_PPS = (s_JamSubfield**) realloc( SubPack_PS->Fields,
SubPack_PS->NumAlloc *
sizeof( s_JamSubfield* ) );
if ( !Fields_PPS )
return JAM_NO_MEMORY;
SubPack_PS->Fields=Fields_PPS;
}
/*
** Copy the passed subfield
*/
/* allocate a new subfield */
NewField_PS = (s_JamSubfield*) malloc( sizeof( s_JamSubfield ) );
if ( !NewField_PS )
return JAM_NO_MEMORY;
/* allocate a new buffer */
if ( Field_PS->DatLen ) {
NewBuf_PC = (char*) malloc( Field_PS->DatLen );
if ( !NewBuf_PC ) {
free (NewField_PS);
return JAM_NO_MEMORY;
}
memcpy( NewBuf_PC, Field_PS->Buffer, Field_PS->DatLen );
}
else
NewBuf_PC = NULL;
/* copy field struct */
NewField_PS->LoID = Field_PS->LoID;
NewField_PS->HiID = Field_PS->HiID;
NewField_PS->DatLen = Field_PS->DatLen;
NewField_PS->Buffer = NewBuf_PC;
/*
** Update subfield packet
*/
SubPack_PS->Fields[ SubPack_PS->NumFields ] = NewField_PS;
SubPack_PS->NumFields++;
return 0;
}

7
deps/libb64-1.2/AUTHORS vendored Executable file
View File

@@ -0,0 +1,7 @@
libb64: Base64 Encoding/Decoding Routines
======================================
Authors:
-------
Chris Venter chris.venter@gmail.com http://rocketpod.blogspot.com

85
deps/libb64-1.2/BENCHMARKS vendored Executable file
View File

@@ -0,0 +1,85 @@
-- Intro
Some people have expressed opinions about how
fast libb64's encoding and decoding routines
are, as compared to some other BASE64 packages
out there.
This document shows the result of a short and sweet
benchmark, which takes a large-ish file and
encodes/decodes it a number of times.
The winner is the executable that does this task the quickest.
-- Platform
The tests were all run on a Fujitsu-Siemens laptop,
with a Pentium M processor running at 2GHz, with
1GB of RAM, running Ubuntu 10.4.
-- Packages
The following BASE64 packages were used in this benchmark:
- libb64-1.2 (libb64-base64)
From libb64.sourceforge.net
Size of executable: 18808 bytes
Compiled with:
CFLAGS += -O3
BUFFERSIZE = 16777216
- base64-1.5 (fourmilab-base64)
From http://www.fourmilab.ch/webtools/base64/
Size of executable: 20261 bytes
Compiled with Default package settings
- coreutils 7.4-2ubuntu2 (coreutils-base64)
From http://www.gnu.org/software/coreutils/
Size of executable: 38488 bytes
Default binary distributed with Ubuntu 10.4
-- Input File
Using blender-2.49b-linux-glibc236-py25-i386.tar.bz2
from http://www.blender.org/download/get-blender/
Size: 18285329 bytes
(approx. 18MB)
-- Method
Encode and Decode the Input file 50 times in a loop,
using a simple shell script, and get the running time.
-- Results
$ time ./benchmark-libb64.sh
real 0m28.389s
user 0m14.077s
sys 0m12.309s
$ time ./benchmark-fourmilab.sh
real 1m43.160s
user 1m23.769s
sys 0m8.737s
$ time ./benchmark-coreutils.sh
real 0m36.288s
user 0m24.746s
sys 0m8.181s
28.389 for 18MB * 50
= 28.389 for 900
-- Conclusion
libb64 is the fastest encoder/decoder, and
has the smallest executable size.
On average it will encode and decode at roughly 31.7MB/second.
The closest "competitor" is base64 from GNU coreutils, which
reaches only 24.8MB/second.
--
14/06/2010
chris.venter@gmail.com

25
deps/libb64-1.2/CHANGELOG vendored Executable file
View File

@@ -0,0 +1,25 @@
libb64: Base64 Encoding/Decoding Routines
======================================
## Changelog ##
Version 1.2 Release
-------------------
Removed the b64dec, b64enc, encoder and decoder programs in favour of
a better example, called base64, which encodes and decodes
depending on its arguments.
Created a solution for Microsoft Visual Studio C++ Express 2010
edition, which simply builds the base64 example as a console application.
Version 1.1 Release
-------------------
Modified encode.h to (correctly) read from the iostream argument,
instead of std::cin.
Thanks to Peter K. Lee for the heads-up.
No API changes.
Version 1.0 Release
-------------------
The current content is the changeset.

44
deps/libb64-1.2/INSTALL vendored Executable file
View File

@@ -0,0 +1,44 @@
libb64: Base64 Encoding/Decoding Routines
======================================
Requirements:
------------
This piece of software has minimal requirements.
I have tested it on the following systems:
- a Linux machine, with the following specs:
(this was the original development machine)
* FedoraCore 4
* kernel v. 2.6.11 (stock FC4 kernel)
* gcc version 4.0.1 20050727 (Red Hat 4.0.1-5)
* glibc-2.3.5-10
* make v. 3.80
* some arb version of makedepend
- Windows XP machine
* MSYS 1.0
* MinGW 5.1.4
* gcc version 3.4.5 (mingw-vista special r3)
- Windows XP machine (same as above)
* Microsoft Visual Studio 2010, Version 10.0.30319.1 RTMRel
Barring any serious screwups on my part, this code should compile and run sweetly
under Cygwin and other systems too. If you DO get it running under some weird arch/os setup,
send me a mail, please.
Compiling:
---------
There is no configure. It would be overkill for something so simple...
Run make in the root directory.
Installing:
----------
Since the current targets are a standalone executable and a static library
(fancy name for archive) with some headers, an install script has not been implemented yet.
Simply copy the executable into your path, and use it.
--
peace out
Chris

29
deps/libb64-1.2/LICENSE vendored Executable file
View File

@@ -0,0 +1,29 @@
Copyright-Only Dedication (based on United States law)
or Public Domain Certification
The person or persons who have associated work with this document (the
"Dedicator" or "Certifier") hereby either (a) certifies that, to the best of
his knowledge, the work of authorship identified is in the public domain of the
country from which the work is published, or (b) hereby dedicates whatever
copyright the dedicators holds in the work of authorship identified below (the
"Work") to the public domain. A certifier, moreover, dedicates any copyright
interest he may have in the associated work, and for these purposes, is
described as a "dedicator" below.
A certifier has taken reasonable steps to verify the copyright status of this
work. Certifier recognizes that his good faith efforts may not shield him from
liability if in fact the work certified is not in the public domain.
Dedicator makes this dedication for the benefit of the public at large and to
the detriment of the Dedicator's heirs and successors. Dedicator intends this
dedication to be an overt act of relinquishment in perpetuity of all present
and future rights under copyright law, whether vested or contingent, in the
Work. Dedicator understands that such relinquishment of all rights includes
the relinquishment of all rights to enforce (by lawsuit or otherwise) those
copyrights in the Work.
Dedicator recognizes that, once placed in the public domain, the Work may be
freely reproduced, distributed, transmitted, used, modified, built upon, or
otherwise exploited by anyone for any purpose, commercial or non-commercial,
and in any way, including by methods that have not yet been invented or
conceived.

25
deps/libb64-1.2/Makefile vendored Executable file
View File

@@ -0,0 +1,25 @@
all: all_src all_base64
all_src:
$(MAKE) -C src
all_base64: all_src
$(MAKE) -C base64
clean: clean_src clean_base64 clean_include
rm -f *~ *.bak
clean_include:
rm -f include/b64/*~
clean_src:
$(MAKE) -C src clean;
clean_base64:
$(MAKE) -C base64 clean;
distclean: clean distclean_src distclean_base64
distclean_src:
$(MAKE) -C src distclean;
distclean_base64:
$(MAKE) -C base64 distclean;

138
deps/libb64-1.2/README vendored Executable file
View File

@@ -0,0 +1,138 @@
b64: Base64 Encoding/Decoding Routines
======================================
Overview:
--------
libb64 is a library of ANSI C routines for fast encoding/decoding data into and
from a base64-encoded format. C++ wrappers are included, as well as the source
code for standalone encoding and decoding executables.
base64 consists of ASCII text, and is therefore a useful encoding for storing
binary data in a text file, such as xml, or sending binary data over text-only
email.
References:
----------
* Wikipedia article:
http://en.wikipedia.org/wiki/Base64
* base64, another implementation of a commandline en/decoder:
http://www.fourmilab.ch/webtools/base64/
Why?
---
I did this because I need an implementation of base64 encoding and decoding,
without any licensing problems. Most OS implementations are released under
either the GNU/GPL, or a BSD-variant, which is not what I require.
Also, the chance to actually use the co-routine implementation in code is rare,
and its use here is fitting. I couldn't pass up the chance.
For more information on this technique, see "Coroutines in C", by Simon Tatham,
which can be found online here:
http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html
So then, under which license do I release this code? On to the next section...
License:
-------
This work is released under into the Public Domain.
It basically boils down to this: I put this work in the public domain, and you
can take it and do whatever you want with it.
An example of this "license" is the Creative Commons Public Domain License, a
copy of which can be found in the LICENSE file, and also online at
http://creativecommons.org/licenses/publicdomain/
Commandline Use:
---------------
There is a new executable available, it is simply called base64.
It can encode and decode files, as instructed by the user.
To encode a file:
$ ./base64 -e filea fileb
fileb will now be the base64-encoded version of filea.
To decode a file:
$ ./base64 -d fileb filec
filec will now be identical to filea.
Programming:
-----------
Some C++ wrappers are provided as well, so you don't have to get your hands
dirty. Encoding from standard input to standard output is as simple as
#include <b64/encode.h>
#include <iostream>
int main()
{
base64::encoder E;
E.encode(std::cin, std::cout);
return 0;
}
Both standalone executables and a static library is provided in the package,
Implementation:
--------------
It is DAMN fast, if I may say so myself. The C code uses a little trick which
has been used to implement coroutines, of which one can say that this
implementation is an example.
(To see how the libb64 codebase compares with some other BASE64 implementations
available, see the BENCHMARKS file)
The trick involves the fact that a switch-statement may legally cross into
sub-blocks. A very thorough and enlightening essay on co-routines in C, using
this method, can be found in the above mentioned "Coroutines in C", by Simon
Tatham: http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html
For example, an RLE decompressing routine, adapted from the article:
1 static int STATE = 0;
2 static int len, c;
3 switch (STATE)
4 {
5 while (1)
6 {
7 c = getchar();
8 if (c == EOF) return EOF;
9 if (c == 0xFF) {
10 len = getchar();
11 c = getchar();
12 while (len--)
13 {
14 STATE = 0;
15 return c;
16 case 0:
17 }
18 } else
19 STATE = 1;
20 return c;
21 case 1:
22 }
23 }
24 }
As can be seen from this example, a coroutine depends on a state variable,
which it sets directly before exiting (lines 14 and 119). The next time the
routine is entered, the switch moves control to the specific point directly
after the previous exit (lines 16 and 21).hands
(As an aside, in the mentioned article the combination of the top-level switch,
the various setting of the state, the return of a value, and the labelling of
the exit point is wrapped in #define macros, making the structure of the
routine even clearer.)
The obvious problem with any such routine is the static keyword.
Any static variables in a function spell doom for multithreaded applications.
Also, in situations where this coroutine is used by more than one other
coroutines, the consistency is disturbed.
What is needed is a structure for storing these variabled, which is passed to
the routine seperately. This obviously breaks the modularity of the function,
since now the caller has to worry about and care for the internal state of the
routine (the callee). This allows for a fast, multithreading-enabled
implementation, which may (obviously) be wrapped in a C++ object for ease of
use.
The base64 encoding and decoding functionality in this package is implemented
in exactly this way, providing both a high-speed high-maintanence C interface,
and a wrapped C++ which is low-maintanence and only slightly less performant.

0
deps/libb64-1.2/TODO vendored Executable file
View File

56
deps/libb64-1.2/base64/Makefile vendored Executable file
View File

@@ -0,0 +1,56 @@
BINARIES = base64
# Build flags (uncomment one)
#############################
# Release build flags
CFLAGS += -O3
#############################
# Debug build flags
#CFLAGS += -g
#############################
# select a buffersize
# a larger size should be faster, but takes more runtime memory
#BUFFERSIZE = 4096
#BUFFERSIZE = 65536
BUFFERSIZE = 16777216
SOURCES = base64.cc
TARGETS = $(BINARIES)
LINK.o = g++
CFLAGS += -Werror -pedantic
CFLAGS += -DBUFFERSIZE=$(BUFFERSIZE)
CFLAGS += -I../include
CXXFLAGS += $(CFLAGS)
vpath %.h ../include/b64
vpath %.a ../src
.PHONY : clean
all: $(TARGETS) #strip
base64: libb64.a
strip:
strip $(BINARIES) *.exe
clean: clean_VisualStudioProject
rm -f *.exe* *.o $(TARGETS) *.bak *~
clean_VisualStudioProject:
$(MAKE) -C VisualStudioProject clean
distclean: clean distclean_VisualStudioProject
rm -f depend
distclean_VisualStudioProject: clean_VisualStudioProject
$(MAKE) -C VisualStudioProject distclean
depend: $(SOURCES)
makedepend -f- $(CFLAGS) $(SOURCES) 2> /dev/null 1> depend
-include depend

View File

@@ -0,0 +1,11 @@
DEBRIS = base64.sdf base64.suo base64.vcxproj.user
all:
clean:
rm -rf Debug Release
distclean: clean
rm -f $(DEBRIS)

View File

@@ -0,0 +1,20 @@

Microsoft Visual Studio Solution File, Format Version 11.00
# Visual C++ Express 2010
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "base64", "base64.vcxproj", "{0B094121-DC64-4D74-AFA0-750B83F800D0}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{0B094121-DC64-4D74-AFA0-750B83F800D0}.Debug|Win32.ActiveCfg = Debug|Win32
{0B094121-DC64-4D74-AFA0-750B83F800D0}.Debug|Win32.Build.0 = Debug|Win32
{0B094121-DC64-4D74-AFA0-750B83F800D0}.Release|Win32.ActiveCfg = Release|Win32
{0B094121-DC64-4D74-AFA0-750B83F800D0}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,92 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{0B094121-DC64-4D74-AFA0-750B83F800D0}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>base64</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>BUFFERSIZE=16777216;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>H:\builds\libb64\working.libb64\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>BUFFERSIZE=16777216;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>H:\builds\libb64\working.libb64\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\src\cdecode.c" />
<ClCompile Include="..\..\src\cencode.c" />
<ClCompile Include="..\base64.cc" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\include\b64\cdecode.h" />
<ClInclude Include="..\..\include\b64\cencode.h" />
<ClInclude Include="..\..\include\b64\decode.h" />
<ClInclude Include="..\..\include\b64\encode.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{12b9f2a2-b899-409a-a507-8cefe9c39b25}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{ce5598bd-67f3-430f-890b-cefa880e9405}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\base64.cc">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\cencode.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\cdecode.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\include\b64\encode.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\include\b64\cdecode.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\include\b64\cencode.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\include\b64\decode.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

BIN
deps/libb64-1.2/base64/base64 vendored Executable file

Binary file not shown.

94
deps/libb64-1.2/base64/base64.cc vendored Executable file
View File

@@ -0,0 +1,94 @@
/*
base64.cc - c++ source to a base64 reference encoder and decoder
This is part of the libb64 project, and has been placed in the public domain.
For details, see http://sourceforge.net/projects/libb64
*/
#include <b64/encode.h>
#include <b64/decode.h>
#include <iostream>
#include <fstream>
#include <string>
#include <stdlib.h>
// Function which prints the usage of this executable
void usage()
{
std::cerr<< \
"base64: Encodes and Decodes files using base64\n" \
"Usage: base64 [-e|-d] [input] [output]\n" \
" Where [-e] will encode the input file into the output file,\n" \
" [-d] will decode the input file into the output file, and\n" \
" [input] and [output] are the input and output files, respectively.\n";
}
// Function which prints the usage of this executable, plus a short message
void usage(const std::string& message)
{
usage();
std::cerr<<"Incorrect invocation of base64:\n";
std::cerr<<message<<std::endl;
}
int main(int argc, char** argv)
{
// Quick check for valid arguments
if (argc == 1)
{
usage();
exit(-1);
}
if (argc != 4)
{
usage("Wrong number of arguments!");
exit(-1);
}
// So far so good; try to open the input file
std::string input = argv[2];
// Note that we have to open the input in binary mode.
// This is due to some operating systems not using binary mode by default.
// Since we will most likely be dealing with binary files when encoding, we
// have to be able to deal with zeros (and other invalid chars) in the input stream.
std::ifstream instream(input.c_str(), std::ios_base::in | std::ios_base::binary);
if (!instream.is_open())
{
usage("Could not open input file!");
exit(-1);
}
// Now try to open the output file
std::string output = argv[3];
// Again, note that we have to open the ouput in binary mode.
// Similiarly, we will most likely need to deal with zeros in the output stream when we
// are decoding, and the output stream has to be able to use these invalid text chars.
std::ofstream outstream(output.c_str(), std::ios_base::out | std::ios_base::binary);
if (!outstream.is_open())
{
usage("Could not open output file!");
exit(-1);
}
// determine whether we need to encode or decode:
std::string choice = argv[1];
if (choice == "-d")
{
base64::decoder D;
D.decode(instream, outstream);
}
else if (choice == "-e")
{
base64::encoder E;
E.encode(instream, outstream);
}
else
{
std::cout<<"["<<choice<<"]"<<std::endl;
usage("Please specify -d or -e as first argument!");
}
return 0;
}

0
deps/libb64-1.2/base64/depend vendored Normal file
View File

28
deps/libb64-1.2/include/b64/cdecode.h vendored Executable file
View File

@@ -0,0 +1,28 @@
/*
cdecode.h - c header for a base64 decoding algorithm
This is part of the libb64 project, and has been placed in the public domain.
For details, see http://sourceforge.net/projects/libb64
*/
#ifndef BASE64_CDECODE_H
#define BASE64_CDECODE_H
typedef enum
{
step_a, step_b, step_c, step_d
} base64_decodestep;
typedef struct
{
base64_decodestep step;
char plainchar;
} base64_decodestate;
void base64_init_decodestate(base64_decodestate* state_in);
int base64_decode_value(char value_in);
int base64_decode_block(const char* code_in, const int length_in, char* plaintext_out, base64_decodestate* state_in);
#endif /* BASE64_CDECODE_H */

31
deps/libb64-1.2/include/b64/cencode.h vendored Executable file
View File

@@ -0,0 +1,31 @@
/*
cencode.h - c header for a base64 encoding algorithm
This is part of the libb64 project, and has been placed in the public domain.
For details, see http://sourceforge.net/projects/libb64
*/
#ifndef BASE64_CENCODE_H
#define BASE64_CENCODE_H
typedef enum
{
step_A, step_B, step_C
} base64_encodestep;
typedef struct
{
base64_encodestep step;
char result;
int stepcount;
} base64_encodestate;
void base64_init_encodestate(base64_encodestate* state_in);
char base64_encode_value(char value_in);
int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in);
int base64_encode_blockend(char* code_out, base64_encodestate* state_in);
#endif /* BASE64_CENCODE_H */

70
deps/libb64-1.2/include/b64/decode.h vendored Executable file
View File

@@ -0,0 +1,70 @@
// :mode=c++:
/*
decode.h - c++ wrapper for a base64 decoding algorithm
This is part of the libb64 project, and has been placed in the public domain.
For details, see http://sourceforge.net/projects/libb64
*/
#ifndef BASE64_DECODE_H
#define BASE64_DECODE_H
#include <iostream>
namespace base64
{
extern "C"
{
#include "cdecode.h"
}
struct decoder
{
base64_decodestate _state;
int _buffersize;
decoder(int buffersize_in = BUFFERSIZE)
: _buffersize(buffersize_in)
{}
int decode(char value_in)
{
return base64_decode_value(value_in);
}
int decode(const char* code_in, const int length_in, char* plaintext_out)
{
return base64_decode_block(code_in, length_in, plaintext_out, &_state);
}
void decode(std::istream& istream_in, std::ostream& ostream_in)
{
base64_init_decodestate(&_state);
//
const int N = _buffersize;
char* code = new char[N];
char* plaintext = new char[N];
int codelength;
int plainlength;
do
{
istream_in.read((char*)code, N);
codelength = istream_in.gcount();
plainlength = decode(code, codelength, plaintext);
ostream_in.write((const char*)plaintext, plainlength);
}
while (istream_in.good() && codelength > 0);
//
base64_init_decodestate(&_state);
delete [] code;
delete [] plaintext;
}
};
} // namespace base64
#endif // BASE64_DECODE_H

77
deps/libb64-1.2/include/b64/encode.h vendored Executable file
View File

@@ -0,0 +1,77 @@
// :mode=c++:
/*
encode.h - c++ wrapper for a base64 encoding algorithm
This is part of the libb64 project, and has been placed in the public domain.
For details, see http://sourceforge.net/projects/libb64
*/
#ifndef BASE64_ENCODE_H
#define BASE64_ENCODE_H
#include <iostream>
namespace base64
{
extern "C"
{
#include "cencode.h"
}
struct encoder
{
base64_encodestate _state;
int _buffersize;
encoder(int buffersize_in = BUFFERSIZE)
: _buffersize(buffersize_in)
{}
int encode(char value_in)
{
return base64_encode_value(value_in);
}
int encode(const char* code_in, const int length_in, char* plaintext_out)
{
return base64_encode_block(code_in, length_in, plaintext_out, &_state);
}
int encode_end(char* plaintext_out)
{
return base64_encode_blockend(plaintext_out, &_state);
}
void encode(std::istream& istream_in, std::ostream& ostream_in)
{
base64_init_encodestate(&_state);
//
const int N = _buffersize;
char* plaintext = new char[N];
char* code = new char[2*N];
int plainlength;
int codelength;
do
{
istream_in.read(plaintext, N);
plainlength = istream_in.gcount();
//
codelength = encode(plaintext, plainlength, code);
ostream_in.write(code, codelength);
}
while (istream_in.good() && plainlength > 0);
codelength = encode_end(code);
ostream_in.write(code, codelength);
//
base64_init_encodestate(&_state);
delete [] code;
delete [] plaintext;
}
};
} // namespace base64
#endif // BASE64_ENCODE_H

43
deps/libb64-1.2/src/Makefile vendored Executable file
View File

@@ -0,0 +1,43 @@
LIBRARIES = libb64.a
# Build flags (uncomment one)
#############################
# Release build flags
CFLAGS += -O3
#############################
# Debug build flags
#CFLAGS += -g
#############################
SOURCES = cdecode.c cencode.c
TARGETS = $(LIBRARIES)
LINK.o = gcc
CFLAGS += -Werror -pedantic
CFLAGS += -I../include
vpath %.h ../include/b64
.PHONY : clean
all: $(TARGETS) #strip
libb64.a: cencode.o cdecode.o
$(AR) $(ARFLAGS) $@ $^
strip:
strip $(BINARIES) *.exe
clean:
rm -f *.exe* *.o $(TARGETS) *.bak *~
distclean: clean
rm -f depend
depend: $(SOURCES)
makedepend -f- $(CFLAGS) $(SOURCES) 2> /dev/null 1> depend
-include depend

88
deps/libb64-1.2/src/cdecode.c vendored Executable file
View File

@@ -0,0 +1,88 @@
/*
cdecoder.c - c source to a base64 decoding algorithm implementation
This is part of the libb64 project, and has been placed in the public domain.
For details, see http://sourceforge.net/projects/libb64
*/
#include <b64/cdecode.h>
int base64_decode_value(char value_in)
{
static const char decoding[] = {62,-1,-1,-1,63,52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-2,-1,-1,-1,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,-1,-1,-1,-1,-1,-1,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};
static const char decoding_size = sizeof(decoding);
value_in -= 43;
if (value_in < 0 || value_in > decoding_size) return -1;
return decoding[(int)value_in];
}
void base64_init_decodestate(base64_decodestate* state_in)
{
state_in->step = step_a;
state_in->plainchar = 0;
}
int base64_decode_block(const char* code_in, const int length_in, char* plaintext_out, base64_decodestate* state_in)
{
const char* codechar = code_in;
char* plainchar = plaintext_out;
char fragment;
*plainchar = state_in->plainchar;
switch (state_in->step)
{
while (1)
{
case step_a:
do {
if (codechar == code_in+length_in)
{
state_in->step = step_a;
state_in->plainchar = *plainchar;
return plainchar - plaintext_out;
}
fragment = (char)base64_decode_value(*codechar++);
} while (fragment < 0);
*plainchar = (fragment & 0x03f) << 2;
case step_b:
do {
if (codechar == code_in+length_in)
{
state_in->step = step_b;
state_in->plainchar = *plainchar;
return plainchar - plaintext_out;
}
fragment = (char)base64_decode_value(*codechar++);
} while (fragment < 0);
*plainchar++ |= (fragment & 0x030) >> 4;
*plainchar = (fragment & 0x00f) << 4;
case step_c:
do {
if (codechar == code_in+length_in)
{
state_in->step = step_c;
state_in->plainchar = *plainchar;
return plainchar - plaintext_out;
}
fragment = (char)base64_decode_value(*codechar++);
} while (fragment < 0);
*plainchar++ |= (fragment & 0x03c) >> 2;
*plainchar = (fragment & 0x003) << 6;
case step_d:
do {
if (codechar == code_in+length_in)
{
state_in->step = step_d;
state_in->plainchar = *plainchar;
return plainchar - plaintext_out;
}
fragment = (char)base64_decode_value(*codechar++);
} while (fragment < 0);
*plainchar++ |= (fragment & 0x03f);
}
}
/* control should not reach here */
return plainchar - plaintext_out;
}

109
deps/libb64-1.2/src/cencode.c vendored Executable file
View File

@@ -0,0 +1,109 @@
/*
cencoder.c - c source to a base64 encoding algorithm implementation
This is part of the libb64 project, and has been placed in the public domain.
For details, see http://sourceforge.net/projects/libb64
*/
#include <b64/cencode.h>
const int CHARS_PER_LINE = 72;
void base64_init_encodestate(base64_encodestate* state_in)
{
state_in->step = step_A;
state_in->result = 0;
state_in->stepcount = 0;
}
char base64_encode_value(char value_in)
{
static const char* encoding = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
if (value_in > 63) return '=';
return encoding[(int)value_in];
}
int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in)
{
const char* plainchar = plaintext_in;
const char* const plaintextend = plaintext_in + length_in;
char* codechar = code_out;
char result;
char fragment;
result = state_in->result;
switch (state_in->step)
{
while (1)
{
case step_A:
if (plainchar == plaintextend)
{
state_in->result = result;
state_in->step = step_A;
return codechar - code_out;
}
fragment = *plainchar++;
result = (fragment & 0x0fc) >> 2;
*codechar++ = base64_encode_value(result);
result = (fragment & 0x003) << 4;
case step_B:
if (plainchar == plaintextend)
{
state_in->result = result;
state_in->step = step_B;
return codechar - code_out;
}
fragment = *plainchar++;
result |= (fragment & 0x0f0) >> 4;
*codechar++ = base64_encode_value(result);
result = (fragment & 0x00f) << 2;
case step_C:
if (plainchar == plaintextend)
{
state_in->result = result;
state_in->step = step_C;
return codechar - code_out;
}
fragment = *plainchar++;
result |= (fragment & 0x0c0) >> 6;
*codechar++ = base64_encode_value(result);
result = (fragment & 0x03f) >> 0;
*codechar++ = base64_encode_value(result);
++(state_in->stepcount);
if (state_in->stepcount == CHARS_PER_LINE/4)
{
*codechar++ = '\n';
state_in->stepcount = 0;
}
}
}
/* control should not reach here */
return codechar - code_out;
}
int base64_encode_blockend(char* code_out, base64_encodestate* state_in)
{
char* codechar = code_out;
switch (state_in->step)
{
case step_B:
*codechar++ = base64_encode_value(state_in->result);
*codechar++ = '=';
*codechar++ = '=';
break;
case step_C:
*codechar++ = base64_encode_value(state_in->result);
*codechar++ = '=';
break;
case step_A:
break;
}
*codechar++ = '\n';
return codechar - code_out;
}

0
deps/libb64-1.2/src/depend vendored Normal file
View File

197
deps/lua/Makefile vendored Normal file
View File

@@ -0,0 +1,197 @@
# Makefile for building Lua
# See ../doc/readme.html for installation and customization instructions.
# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT =======================
# Your platform. See PLATS for possible values.
PLAT= none
CC= gcc -std=gnu99
CFLAGS= -O2 -Wall -Wextra -DLUA_COMPAT_5_2 $(SYSCFLAGS) $(MYCFLAGS)
LDFLAGS= $(SYSLDFLAGS) $(MYLDFLAGS)
LIBS= -lm $(SYSLIBS) $(MYLIBS)
AR= ar rcu
RANLIB= ranlib
RM= rm -f
SYSCFLAGS=
SYSLDFLAGS=
SYSLIBS=
MYCFLAGS=
MYLDFLAGS=
MYLIBS=
MYOBJS=
# == END OF USER SETTINGS -- NO NEED TO CHANGE ANYTHING BELOW THIS LINE =======
PLATS= aix bsd c89 freebsd generic linux macosx mingw posix solaris
LUA_A= liblua.a
CORE_O= lapi.o lcode.o lctype.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o \
lmem.o lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o \
ltm.o lundump.o lvm.o lzio.o
LIB_O= lauxlib.o lbaselib.o lbitlib.o lcorolib.o ldblib.o liolib.o \
lmathlib.o loslib.o lstrlib.o ltablib.o lutf8lib.o loadlib.o linit.o
BASE_O= $(CORE_O) $(LIB_O) $(MYOBJS)
LUA_T= lua
LUA_O= lua.o
LUAC_T= luac
LUAC_O= luac.o
ALL_O= $(BASE_O) $(LUA_O) $(LUAC_O)
ALL_T= $(LUA_A) $(LUA_T) $(LUAC_T)
ALL_A= $(LUA_A)
# Targets start here.
default: $(PLAT)
all: $(ALL_T)
o: $(ALL_O)
a: $(ALL_A)
$(LUA_A): $(BASE_O)
$(AR) $@ $(BASE_O)
$(RANLIB) $@
$(LUA_T): $(LUA_O) $(LUA_A)
$(CC) -o $@ $(LDFLAGS) $(LUA_O) $(LUA_A) $(LIBS)
$(LUAC_T): $(LUAC_O) $(LUA_A)
$(CC) -o $@ $(LDFLAGS) $(LUAC_O) $(LUA_A) $(LIBS)
clean:
$(RM) $(ALL_T) $(ALL_O)
depend:
@$(CC) $(CFLAGS) -MM l*.c
echo:
@echo "PLAT= $(PLAT)"
@echo "CC= $(CC)"
@echo "CFLAGS= $(CFLAGS)"
@echo "LDFLAGS= $(SYSLDFLAGS)"
@echo "LIBS= $(LIBS)"
@echo "AR= $(AR)"
@echo "RANLIB= $(RANLIB)"
@echo "RM= $(RM)"
# Convenience targets for popular platforms
ALL= all
none:
@echo "Please do 'make PLATFORM' where PLATFORM is one of these:"
@echo " $(PLATS)"
aix:
$(MAKE) $(ALL) CC="xlc" CFLAGS="-O2 -DLUA_USE_POSIX -DLUA_USE_DLOPEN" SYSLIBS="-ldl" SYSLDFLAGS="-brtl -bexpall"
bsd:
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" SYSLIBS="-Wl,-E"
c89:
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_C89" CC="gcc -std=c89"
@echo ''
@echo '*** C89 does not guarantee 64-bit integers for Lua.'
@echo ''
freebsd:
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX -I/usr/local/include" SYSLIBS="-L/usr/local/lib -Wl,-E -lreadline" CC=cc
generic: $(ALL)
linux:
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX" SYSLIBS="-Wl,-E -ldl -lreadline"
macosx:
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_MACOSX" SYSLIBS="-lreadline" CC=cc
mingw:
$(MAKE) "LUA_A=lua53.dll" "LUA_T=lua.exe" \
"AR=$(CC) -shared -o" "RANLIB=strip --strip-unneeded" \
"SYSCFLAGS=-DLUA_BUILD_AS_DLL" "SYSLIBS=" "SYSLDFLAGS=-s" lua.exe
$(MAKE) "LUAC_T=luac.exe" luac.exe
posix:
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX"
solaris:
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN -D_REENTRANT" SYSLIBS="-ldl"
# list targets that do not create files (but not all makes understand .PHONY)
.PHONY: all $(PLATS) default o a clean depend echo none
# DO NOT DELETE
lapi.o: lapi.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \
lobject.h ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h lstring.h \
ltable.h lundump.h lvm.h
lauxlib.o: lauxlib.c lprefix.h lua.h luaconf.h lauxlib.h
lbaselib.o: lbaselib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
lbitlib.o: lbitlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
lcode.o: lcode.c lprefix.h lua.h luaconf.h lcode.h llex.h lobject.h \
llimits.h lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h \
ldo.h lgc.h lstring.h ltable.h lvm.h
lcorolib.o: lcorolib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
lctype.o: lctype.c lprefix.h lctype.h lua.h luaconf.h llimits.h
ldblib.o: ldblib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
ldebug.o: ldebug.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \
lobject.h ltm.h lzio.h lmem.h lcode.h llex.h lopcodes.h lparser.h \
ldebug.h ldo.h lfunc.h lstring.h lgc.h ltable.h lvm.h
ldo.o: ldo.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \
lobject.h ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h lopcodes.h \
lparser.h lstring.h ltable.h lundump.h lvm.h
ldump.o: ldump.c lprefix.h lua.h luaconf.h lobject.h llimits.h lstate.h \
ltm.h lzio.h lmem.h lundump.h
lfunc.o: lfunc.c lprefix.h lua.h luaconf.h lfunc.h lobject.h llimits.h \
lgc.h lstate.h ltm.h lzio.h lmem.h
lgc.o: lgc.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h lstring.h ltable.h
linit.o: linit.c lprefix.h lua.h luaconf.h lualib.h lauxlib.h
liolib.o: liolib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
llex.o: llex.c lprefix.h lua.h luaconf.h lctype.h llimits.h ldebug.h \
lstate.h lobject.h ltm.h lzio.h lmem.h ldo.h lgc.h llex.h lparser.h \
lstring.h ltable.h
lmathlib.o: lmathlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
lmem.o: lmem.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
llimits.h ltm.h lzio.h lmem.h ldo.h lgc.h
loadlib.o: loadlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
lobject.o: lobject.c lprefix.h lua.h luaconf.h lctype.h llimits.h \
ldebug.h lstate.h lobject.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h \
lvm.h
lopcodes.o: lopcodes.c lprefix.h lopcodes.h llimits.h lua.h luaconf.h
loslib.o: loslib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
lparser.o: lparser.c lprefix.h lua.h luaconf.h lcode.h llex.h lobject.h \
llimits.h lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h \
ldo.h lfunc.h lstring.h lgc.h ltable.h
lstate.o: lstate.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \
lobject.h ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h llex.h \
lstring.h ltable.h
lstring.o: lstring.c lprefix.h lua.h luaconf.h ldebug.h lstate.h \
lobject.h llimits.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h
lstrlib.o: lstrlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
ltable.o: ltable.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
llimits.h ltm.h lzio.h lmem.h ldo.h lgc.h lstring.h ltable.h lvm.h
ltablib.o: ltablib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
ltm.o: ltm.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
llimits.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h ltable.h lvm.h
lua.o: lua.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
luac.o: luac.c lprefix.h lua.h luaconf.h lauxlib.h lobject.h llimits.h \
lstate.h ltm.h lzio.h lmem.h lundump.h ldebug.h lopcodes.h
lundump.o: lundump.c lprefix.h lua.h luaconf.h ldebug.h lstate.h \
lobject.h llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lstring.h lgc.h \
lundump.h
lutf8lib.o: lutf8lib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
lvm.o: lvm.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h lopcodes.h lstring.h \
ltable.h lvm.h
lzio.o: lzio.c lprefix.h lua.h luaconf.h llimits.h lmem.h lstate.h \
lobject.h ltm.h lzio.h
# (end of Makefile)

1298
deps/lua/lapi.c vendored Normal file

File diff suppressed because it is too large Load Diff

24
deps/lua/lapi.h vendored Normal file
View File

@@ -0,0 +1,24 @@
/*
** $Id: lapi.h,v 2.9 2015/03/06 19:49:50 roberto Exp $
** Auxiliary functions from Lua API
** See Copyright Notice in lua.h
*/
#ifndef lapi_h
#define lapi_h
#include "llimits.h"
#include "lstate.h"
#define api_incr_top(L) {L->top++; api_check(L, L->top <= L->ci->top, \
"stack overflow");}
#define adjustresults(L,nres) \
{ if ((nres) == LUA_MULTRET && L->ci->top < L->top) L->ci->top = L->top; }
#define api_checknelems(L,n) api_check(L, (n) < (L->top - L->ci->func), \
"not enough elements in the stack")
#endif

1035
deps/lua/lauxlib.c vendored Normal file

File diff suppressed because it is too large Load Diff

256
deps/lua/lauxlib.h vendored Normal file
View File

@@ -0,0 +1,256 @@
/*
** $Id: lauxlib.h,v 1.129 2015/11/23 11:29:43 roberto Exp $
** Auxiliary functions for building Lua libraries
** See Copyright Notice in lua.h
*/
#ifndef lauxlib_h
#define lauxlib_h
#include <stddef.h>
#include <stdio.h>
#include "lua.h"
/* extra error code for 'luaL_load' */
#define LUA_ERRFILE (LUA_ERRERR+1)
typedef struct luaL_Reg {
const char *name;
lua_CFunction func;
} luaL_Reg;
#define LUAL_NUMSIZES (sizeof(lua_Integer)*16 + sizeof(lua_Number))
LUALIB_API void (luaL_checkversion_) (lua_State *L, lua_Number ver, size_t sz);
#define luaL_checkversion(L) \
luaL_checkversion_(L, LUA_VERSION_NUM, LUAL_NUMSIZES)
LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e);
LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e);
LUALIB_API const char *(luaL_tolstring) (lua_State *L, int idx, size_t *len);
LUALIB_API int (luaL_argerror) (lua_State *L, int arg, const char *extramsg);
LUALIB_API const char *(luaL_checklstring) (lua_State *L, int arg,
size_t *l);
LUALIB_API const char *(luaL_optlstring) (lua_State *L, int arg,
const char *def, size_t *l);
LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int arg);
LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int arg, lua_Number def);
LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int arg);
LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int arg,
lua_Integer def);
LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg);
LUALIB_API void (luaL_checktype) (lua_State *L, int arg, int t);
LUALIB_API void (luaL_checkany) (lua_State *L, int arg);
LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname);
LUALIB_API void (luaL_setmetatable) (lua_State *L, const char *tname);
LUALIB_API void *(luaL_testudata) (lua_State *L, int ud, const char *tname);
LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname);
LUALIB_API void (luaL_where) (lua_State *L, int lvl);
LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...);
LUALIB_API int (luaL_checkoption) (lua_State *L, int arg, const char *def,
const char *const lst[]);
LUALIB_API int (luaL_fileresult) (lua_State *L, int stat, const char *fname);
LUALIB_API int (luaL_execresult) (lua_State *L, int stat);
/* predefined references */
#define LUA_NOREF (-2)
#define LUA_REFNIL (-1)
LUALIB_API int (luaL_ref) (lua_State *L, int t);
LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref);
LUALIB_API int (luaL_loadfilex) (lua_State *L, const char *filename,
const char *mode);
#define luaL_loadfile(L,f) luaL_loadfilex(L,f,NULL)
LUALIB_API int (luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz,
const char *name, const char *mode);
LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s);
LUALIB_API lua_State *(luaL_newstate) (void);
LUALIB_API lua_Integer (luaL_len) (lua_State *L, int idx);
LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p,
const char *r);
LUALIB_API void (luaL_setfuncs) (lua_State *L, const luaL_Reg *l, int nup);
LUALIB_API int (luaL_getsubtable) (lua_State *L, int idx, const char *fname);
LUALIB_API void (luaL_traceback) (lua_State *L, lua_State *L1,
const char *msg, int level);
LUALIB_API void (luaL_requiref) (lua_State *L, const char *modname,
lua_CFunction openf, int glb);
/*
** ===============================================================
** some useful macros
** ===============================================================
*/
#define luaL_newlibtable(L,l) \
lua_createtable(L, 0, sizeof(l)/sizeof((l)[0]) - 1)
#define luaL_newlib(L,l) \
(luaL_checkversion(L), luaL_newlibtable(L,l), luaL_setfuncs(L,l,0))
#define luaL_argcheck(L, cond,arg,extramsg) \
((void)((cond) || luaL_argerror(L, (arg), (extramsg))))
#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL))
#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL))
#define luaL_typename(L,i) lua_typename(L, lua_type(L,(i)))
#define luaL_dofile(L, fn) \
(luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0))
#define luaL_dostring(L, s) \
(luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0))
#define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n)))
#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n)))
#define luaL_loadbuffer(L,s,sz,n) luaL_loadbufferx(L,s,sz,n,NULL)
/*
** {======================================================
** Generic Buffer manipulation
** =======================================================
*/
typedef struct luaL_Buffer {
char *b; /* buffer address */
size_t size; /* buffer size */
size_t n; /* number of characters in buffer */
lua_State *L;
char initb[LUAL_BUFFERSIZE]; /* initial buffer */
} luaL_Buffer;
#define luaL_addchar(B,c) \
((void)((B)->n < (B)->size || luaL_prepbuffsize((B), 1)), \
((B)->b[(B)->n++] = (c)))
#define luaL_addsize(B,s) ((B)->n += (s))
LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B);
LUALIB_API char *(luaL_prepbuffsize) (luaL_Buffer *B, size_t sz);
LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l);
LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s);
LUALIB_API void (luaL_addvalue) (luaL_Buffer *B);
LUALIB_API void (luaL_pushresult) (luaL_Buffer *B);
LUALIB_API void (luaL_pushresultsize) (luaL_Buffer *B, size_t sz);
LUALIB_API char *(luaL_buffinitsize) (lua_State *L, luaL_Buffer *B, size_t sz);
#define luaL_prepbuffer(B) luaL_prepbuffsize(B, LUAL_BUFFERSIZE)
/* }====================================================== */
/*
** {======================================================
** File handles for IO library
** =======================================================
*/
/*
** A file handle is a userdata with metatable 'LUA_FILEHANDLE' and
** initial structure 'luaL_Stream' (it may contain other fields
** after that initial structure).
*/
#define LUA_FILEHANDLE "FILE*"
typedef struct luaL_Stream {
FILE *f; /* stream (NULL for incompletely created streams) */
lua_CFunction closef; /* to close stream (NULL for closed streams) */
} luaL_Stream;
/* }====================================================== */
/* compatibility with old module system */
#if defined(LUA_COMPAT_MODULE)
LUALIB_API void (luaL_pushmodule) (lua_State *L, const char *modname,
int sizehint);
LUALIB_API void (luaL_openlib) (lua_State *L, const char *libname,
const luaL_Reg *l, int nup);
#define luaL_register(L,n,l) (luaL_openlib(L,(n),(l),0))
#endif
/*
** {==================================================================
** "Abstraction Layer" for basic report of messages and errors
** ===================================================================
*/
/* print a string */
#if !defined(lua_writestring)
#define lua_writestring(s,l) fwrite((s), sizeof(char), (l), stdout)
#endif
/* print a newline and flush the output */
#if !defined(lua_writeline)
#define lua_writeline() (lua_writestring("\n", 1), fflush(stdout))
#endif
/* print an error message */
#if !defined(lua_writestringerror)
#define lua_writestringerror(s,p) \
(fprintf(stderr, (s), (p)), fflush(stderr))
#endif
/* }================================================================== */
/*
** {============================================================
** Compatibility with deprecated conversions
** =============================================================
*/
#if defined(LUA_COMPAT_APIINTCASTS)
#define luaL_checkunsigned(L,a) ((lua_Unsigned)luaL_checkinteger(L,a))
#define luaL_optunsigned(L,a,d) \
((lua_Unsigned)luaL_optinteger(L,a,(lua_Integer)(d)))
#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n)))
#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d)))
#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n)))
#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d)))
#endif
/* }============================================================ */
#endif

498
deps/lua/lbaselib.c vendored Normal file
View File

@@ -0,0 +1,498 @@
/*
** $Id: lbaselib.c,v 1.313 2016/04/11 19:18:40 roberto Exp $
** Basic library
** See Copyright Notice in lua.h
*/
#define lbaselib_c
#define LUA_LIB
#include "lprefix.h"
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
static int luaB_print (lua_State *L) {
int n = lua_gettop(L); /* number of arguments */
int i;
lua_getglobal(L, "tostring");
for (i=1; i<=n; i++) {
const char *s;
size_t l;
lua_pushvalue(L, -1); /* function to be called */
lua_pushvalue(L, i); /* value to print */
lua_call(L, 1, 1);
s = lua_tolstring(L, -1, &l); /* get result */
if (s == NULL)
return luaL_error(L, "'tostring' must return a string to 'print'");
if (i>1) lua_writestring("\t", 1);
lua_writestring(s, l);
lua_pop(L, 1); /* pop result */
}
lua_writeline();
return 0;
}
#define SPACECHARS " \f\n\r\t\v"
static const char *b_str2int (const char *s, int base, lua_Integer *pn) {
lua_Unsigned n = 0;
int neg = 0;
s += strspn(s, SPACECHARS); /* skip initial spaces */
if (*s == '-') { s++; neg = 1; } /* handle signal */
else if (*s == '+') s++;
if (!isalnum((unsigned char)*s)) /* no digit? */
return NULL;
do {
int digit = (isdigit((unsigned char)*s)) ? *s - '0'
: (toupper((unsigned char)*s) - 'A') + 10;
if (digit >= base) return NULL; /* invalid numeral */
n = n * base + digit;
s++;
} while (isalnum((unsigned char)*s));
s += strspn(s, SPACECHARS); /* skip trailing spaces */
*pn = (lua_Integer)((neg) ? (0u - n) : n);
return s;
}
static int luaB_tonumber (lua_State *L) {
if (lua_isnoneornil(L, 2)) { /* standard conversion? */
luaL_checkany(L, 1);
if (lua_type(L, 1) == LUA_TNUMBER) { /* already a number? */
lua_settop(L, 1); /* yes; return it */
return 1;
}
else {
size_t l;
const char *s = lua_tolstring(L, 1, &l);
if (s != NULL && lua_stringtonumber(L, s) == l + 1)
return 1; /* successful conversion to number */
/* else not a number */
}
}
else {
size_t l;
const char *s;
lua_Integer n = 0; /* to avoid warnings */
lua_Integer base = luaL_checkinteger(L, 2);
luaL_checktype(L, 1, LUA_TSTRING); /* no numbers as strings */
s = lua_tolstring(L, 1, &l);
luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range");
if (b_str2int(s, (int)base, &n) == s + l) {
lua_pushinteger(L, n);
return 1;
} /* else not a number */
} /* else not a number */
lua_pushnil(L); /* not a number */
return 1;
}
static int luaB_error (lua_State *L) {
int level = (int)luaL_optinteger(L, 2, 1);
lua_settop(L, 1);
if (lua_type(L, 1) == LUA_TSTRING && level > 0) {
luaL_where(L, level); /* add extra information */
lua_pushvalue(L, 1);
lua_concat(L, 2);
}
return lua_error(L);
}
static int luaB_getmetatable (lua_State *L) {
luaL_checkany(L, 1);
if (!lua_getmetatable(L, 1)) {
lua_pushnil(L);
return 1; /* no metatable */
}
luaL_getmetafield(L, 1, "__metatable");
return 1; /* returns either __metatable field (if present) or metatable */
}
static int luaB_setmetatable (lua_State *L) {
int t = lua_type(L, 2);
luaL_checktype(L, 1, LUA_TTABLE);
luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,
"nil or table expected");
if (luaL_getmetafield(L, 1, "__metatable") != LUA_TNIL)
return luaL_error(L, "cannot change a protected metatable");
lua_settop(L, 2);
lua_setmetatable(L, 1);
return 1;
}
static int luaB_rawequal (lua_State *L) {
luaL_checkany(L, 1);
luaL_checkany(L, 2);
lua_pushboolean(L, lua_rawequal(L, 1, 2));
return 1;
}
static int luaB_rawlen (lua_State *L) {
int t = lua_type(L, 1);
luaL_argcheck(L, t == LUA_TTABLE || t == LUA_TSTRING, 1,
"table or string expected");
lua_pushinteger(L, lua_rawlen(L, 1));
return 1;
}
static int luaB_rawget (lua_State *L) {
luaL_checktype(L, 1, LUA_TTABLE);
luaL_checkany(L, 2);
lua_settop(L, 2);
lua_rawget(L, 1);
return 1;
}
static int luaB_rawset (lua_State *L) {
luaL_checktype(L, 1, LUA_TTABLE);
luaL_checkany(L, 2);
luaL_checkany(L, 3);
lua_settop(L, 3);
lua_rawset(L, 1);
return 1;
}
static int luaB_collectgarbage (lua_State *L) {
static const char *const opts[] = {"stop", "restart", "collect",
"count", "step", "setpause", "setstepmul",
"isrunning", NULL};
static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT,
LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL,
LUA_GCISRUNNING};
int o = optsnum[luaL_checkoption(L, 1, "collect", opts)];
int ex = (int)luaL_optinteger(L, 2, 0);
int res = lua_gc(L, o, ex);
switch (o) {
case LUA_GCCOUNT: {
int b = lua_gc(L, LUA_GCCOUNTB, 0);
lua_pushnumber(L, (lua_Number)res + ((lua_Number)b/1024));
return 1;
}
case LUA_GCSTEP: case LUA_GCISRUNNING: {
lua_pushboolean(L, res);
return 1;
}
default: {
lua_pushinteger(L, res);
return 1;
}
}
}
static int luaB_type (lua_State *L) {
int t = lua_type(L, 1);
luaL_argcheck(L, t != LUA_TNONE, 1, "value expected");
lua_pushstring(L, lua_typename(L, t));
return 1;
}
static int pairsmeta (lua_State *L, const char *method, int iszero,
lua_CFunction iter) {
if (luaL_getmetafield(L, 1, method) == LUA_TNIL) { /* no metamethod? */
luaL_checktype(L, 1, LUA_TTABLE); /* argument must be a table */
lua_pushcfunction(L, iter); /* will return generator, */
lua_pushvalue(L, 1); /* state, */
if (iszero) lua_pushinteger(L, 0); /* and initial value */
else lua_pushnil(L);
}
else {
lua_pushvalue(L, 1); /* argument 'self' to metamethod */
lua_call(L, 1, 3); /* get 3 values from metamethod */
}
return 3;
}
static int luaB_next (lua_State *L) {
luaL_checktype(L, 1, LUA_TTABLE);
lua_settop(L, 2); /* create a 2nd argument if there isn't one */
if (lua_next(L, 1))
return 2;
else {
lua_pushnil(L);
return 1;
}
}
static int luaB_pairs (lua_State *L) {
return pairsmeta(L, "__pairs", 0, luaB_next);
}
/*
** Traversal function for 'ipairs'
*/
static int ipairsaux (lua_State *L) {
lua_Integer i = luaL_checkinteger(L, 2) + 1;
lua_pushinteger(L, i);
return (lua_geti(L, 1, i) == LUA_TNIL) ? 1 : 2;
}
/*
** 'ipairs' function. Returns 'ipairsaux', given "table", 0.
** (The given "table" may not be a table.)
*/
static int luaB_ipairs (lua_State *L) {
#if defined(LUA_COMPAT_IPAIRS)
return pairsmeta(L, "__ipairs", 1, ipairsaux);
#else
luaL_checkany(L, 1);
lua_pushcfunction(L, ipairsaux); /* iteration function */
lua_pushvalue(L, 1); /* state */
lua_pushinteger(L, 0); /* initial value */
return 3;
#endif
}
static int load_aux (lua_State *L, int status, int envidx) {
if (status == LUA_OK) {
if (envidx != 0) { /* 'env' parameter? */
lua_pushvalue(L, envidx); /* environment for loaded function */
if (!lua_setupvalue(L, -2, 1)) /* set it as 1st upvalue */
lua_pop(L, 1); /* remove 'env' if not used by previous call */
}
return 1;
}
else { /* error (message is on top of the stack) */
lua_pushnil(L);
lua_insert(L, -2); /* put before error message */
return 2; /* return nil plus error message */
}
}
static int luaB_loadfile (lua_State *L) {
const char *fname = luaL_optstring(L, 1, NULL);
const char *mode = luaL_optstring(L, 2, NULL);
int env = (!lua_isnone(L, 3) ? 3 : 0); /* 'env' index or 0 if no 'env' */
int status = luaL_loadfilex(L, fname, mode);
return load_aux(L, status, env);
}
/*
** {======================================================
** Generic Read function
** =======================================================
*/
/*
** reserved slot, above all arguments, to hold a copy of the returned
** string to avoid it being collected while parsed. 'load' has four
** optional arguments (chunk, source name, mode, and environment).
*/
#define RESERVEDSLOT 5
/*
** Reader for generic 'load' function: 'lua_load' uses the
** stack for internal stuff, so the reader cannot change the
** stack top. Instead, it keeps its resulting string in a
** reserved slot inside the stack.
*/
static const char *generic_reader (lua_State *L, void *ud, size_t *size) {
(void)(ud); /* not used */
luaL_checkstack(L, 2, "too many nested functions");
lua_pushvalue(L, 1); /* get function */
lua_call(L, 0, 1); /* call it */
if (lua_isnil(L, -1)) {
lua_pop(L, 1); /* pop result */
*size = 0;
return NULL;
}
else if (!lua_isstring(L, -1))
luaL_error(L, "reader function must return a string");
lua_replace(L, RESERVEDSLOT); /* save string in reserved slot */
return lua_tolstring(L, RESERVEDSLOT, size);
}
static int luaB_load (lua_State *L) {
int status;
size_t l;
const char *s = lua_tolstring(L, 1, &l);
const char *mode = luaL_optstring(L, 3, "bt");
int env = (!lua_isnone(L, 4) ? 4 : 0); /* 'env' index or 0 if no 'env' */
if (s != NULL) { /* loading a string? */
const char *chunkname = luaL_optstring(L, 2, s);
status = luaL_loadbufferx(L, s, l, chunkname, mode);
}
else { /* loading from a reader function */
const char *chunkname = luaL_optstring(L, 2, "=(load)");
luaL_checktype(L, 1, LUA_TFUNCTION);
lua_settop(L, RESERVEDSLOT); /* create reserved slot */
status = lua_load(L, generic_reader, NULL, chunkname, mode);
}
return load_aux(L, status, env);
}
/* }====================================================== */
static int dofilecont (lua_State *L, int d1, lua_KContext d2) {
(void)d1; (void)d2; /* only to match 'lua_Kfunction' prototype */
return lua_gettop(L) - 1;
}
static int luaB_dofile (lua_State *L) {
const char *fname = luaL_optstring(L, 1, NULL);
lua_settop(L, 1);
if (luaL_loadfile(L, fname) != LUA_OK)
return lua_error(L);
lua_callk(L, 0, LUA_MULTRET, 0, dofilecont);
return dofilecont(L, 0, 0);
}
static int luaB_assert (lua_State *L) {
if (lua_toboolean(L, 1)) /* condition is true? */
return lua_gettop(L); /* return all arguments */
else { /* error */
luaL_checkany(L, 1); /* there must be a condition */
lua_remove(L, 1); /* remove it */
lua_pushliteral(L, "assertion failed!"); /* default message */
lua_settop(L, 1); /* leave only message (default if no other one) */
return luaB_error(L); /* call 'error' */
}
}
static int luaB_select (lua_State *L) {
int n = lua_gettop(L);
if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') {
lua_pushinteger(L, n-1);
return 1;
}
else {
lua_Integer i = luaL_checkinteger(L, 1);
if (i < 0) i = n + i;
else if (i > n) i = n;
luaL_argcheck(L, 1 <= i, 1, "index out of range");
return n - (int)i;
}
}
/*
** Continuation function for 'pcall' and 'xpcall'. Both functions
** already pushed a 'true' before doing the call, so in case of success
** 'finishpcall' only has to return everything in the stack minus
** 'extra' values (where 'extra' is exactly the number of items to be
** ignored).
*/
static int finishpcall (lua_State *L, int status, lua_KContext extra) {
if (status != LUA_OK && status != LUA_YIELD) { /* error? */
lua_pushboolean(L, 0); /* first result (false) */
lua_pushvalue(L, -2); /* error message */
return 2; /* return false, msg */
}
else
return lua_gettop(L) - (int)extra; /* return all results */
}
static int luaB_pcall (lua_State *L) {
int status;
luaL_checkany(L, 1);
lua_pushboolean(L, 1); /* first result if no errors */
lua_insert(L, 1); /* put it in place */
status = lua_pcallk(L, lua_gettop(L) - 2, LUA_MULTRET, 0, 0, finishpcall);
return finishpcall(L, status, 0);
}
/*
** Do a protected call with error handling. After 'lua_rotate', the
** stack will have <f, err, true, f, [args...]>; so, the function passes
** 2 to 'finishpcall' to skip the 2 first values when returning results.
*/
static int luaB_xpcall (lua_State *L) {
int status;
int n = lua_gettop(L);
luaL_checktype(L, 2, LUA_TFUNCTION); /* check error function */
lua_pushboolean(L, 1); /* first result */
lua_pushvalue(L, 1); /* function */
lua_rotate(L, 3, 2); /* move them below function's arguments */
status = lua_pcallk(L, n - 2, LUA_MULTRET, 2, 2, finishpcall);
return finishpcall(L, status, 2);
}
static int luaB_tostring (lua_State *L) {
luaL_checkany(L, 1);
luaL_tolstring(L, 1, NULL);
return 1;
}
static const luaL_Reg base_funcs[] = {
{"assert", luaB_assert},
{"collectgarbage", luaB_collectgarbage},
{"dofile", luaB_dofile},
{"error", luaB_error},
{"getmetatable", luaB_getmetatable},
{"ipairs", luaB_ipairs},
{"loadfile", luaB_loadfile},
{"load", luaB_load},
#if defined(LUA_COMPAT_LOADSTRING)
{"loadstring", luaB_load},
#endif
{"next", luaB_next},
{"pairs", luaB_pairs},
{"pcall", luaB_pcall},
{"print", luaB_print},
{"rawequal", luaB_rawequal},
{"rawlen", luaB_rawlen},
{"rawget", luaB_rawget},
{"rawset", luaB_rawset},
{"select", luaB_select},
{"setmetatable", luaB_setmetatable},
{"tonumber", luaB_tonumber},
{"tostring", luaB_tostring},
{"type", luaB_type},
{"xpcall", luaB_xpcall},
/* placeholders */
{"_G", NULL},
{"_VERSION", NULL},
{NULL, NULL}
};
LUAMOD_API int luaopen_base (lua_State *L) {
/* open lib into global table */
lua_pushglobaltable(L);
luaL_setfuncs(L, base_funcs, 0);
/* set global _G */
lua_pushvalue(L, -1);
lua_setfield(L, -2, "_G");
/* set global _VERSION */
lua_pushliteral(L, LUA_VERSION);
lua_setfield(L, -2, "_VERSION");
return 1;
}

233
deps/lua/lbitlib.c vendored Normal file
View File

@@ -0,0 +1,233 @@
/*
** $Id: lbitlib.c,v 1.30 2015/11/11 19:08:09 roberto Exp $
** Standard library for bitwise operations
** See Copyright Notice in lua.h
*/
#define lbitlib_c
#define LUA_LIB
#include "lprefix.h"
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
#if defined(LUA_COMPAT_BITLIB) /* { */
#define pushunsigned(L,n) lua_pushinteger(L, (lua_Integer)(n))
#define checkunsigned(L,i) ((lua_Unsigned)luaL_checkinteger(L,i))
/* number of bits to consider in a number */
#if !defined(LUA_NBITS)
#define LUA_NBITS 32
#endif
/*
** a lua_Unsigned with its first LUA_NBITS bits equal to 1. (Shift must
** be made in two parts to avoid problems when LUA_NBITS is equal to the
** number of bits in a lua_Unsigned.)
*/
#define ALLONES (~(((~(lua_Unsigned)0) << (LUA_NBITS - 1)) << 1))
/* macro to trim extra bits */
#define trim(x) ((x) & ALLONES)
/* builds a number with 'n' ones (1 <= n <= LUA_NBITS) */
#define mask(n) (~((ALLONES << 1) << ((n) - 1)))
static lua_Unsigned andaux (lua_State *L) {
int i, n = lua_gettop(L);
lua_Unsigned r = ~(lua_Unsigned)0;
for (i = 1; i <= n; i++)
r &= checkunsigned(L, i);
return trim(r);
}
static int b_and (lua_State *L) {
lua_Unsigned r = andaux(L);
pushunsigned(L, r);
return 1;
}
static int b_test (lua_State *L) {
lua_Unsigned r = andaux(L);
lua_pushboolean(L, r != 0);
return 1;
}
static int b_or (lua_State *L) {
int i, n = lua_gettop(L);
lua_Unsigned r = 0;
for (i = 1; i <= n; i++)
r |= checkunsigned(L, i);
pushunsigned(L, trim(r));
return 1;
}
static int b_xor (lua_State *L) {
int i, n = lua_gettop(L);
lua_Unsigned r = 0;
for (i = 1; i <= n; i++)
r ^= checkunsigned(L, i);
pushunsigned(L, trim(r));
return 1;
}
static int b_not (lua_State *L) {
lua_Unsigned r = ~checkunsigned(L, 1);
pushunsigned(L, trim(r));
return 1;
}
static int b_shift (lua_State *L, lua_Unsigned r, lua_Integer i) {
if (i < 0) { /* shift right? */
i = -i;
r = trim(r);
if (i >= LUA_NBITS) r = 0;
else r >>= i;
}
else { /* shift left */
if (i >= LUA_NBITS) r = 0;
else r <<= i;
r = trim(r);
}
pushunsigned(L, r);
return 1;
}
static int b_lshift (lua_State *L) {
return b_shift(L, checkunsigned(L, 1), luaL_checkinteger(L, 2));
}
static int b_rshift (lua_State *L) {
return b_shift(L, checkunsigned(L, 1), -luaL_checkinteger(L, 2));
}
static int b_arshift (lua_State *L) {
lua_Unsigned r = checkunsigned(L, 1);
lua_Integer i = luaL_checkinteger(L, 2);
if (i < 0 || !(r & ((lua_Unsigned)1 << (LUA_NBITS - 1))))
return b_shift(L, r, -i);
else { /* arithmetic shift for 'negative' number */
if (i >= LUA_NBITS) r = ALLONES;
else
r = trim((r >> i) | ~(trim(~(lua_Unsigned)0) >> i)); /* add signal bit */
pushunsigned(L, r);
return 1;
}
}
static int b_rot (lua_State *L, lua_Integer d) {
lua_Unsigned r = checkunsigned(L, 1);
int i = d & (LUA_NBITS - 1); /* i = d % NBITS */
r = trim(r);
if (i != 0) /* avoid undefined shift of LUA_NBITS when i == 0 */
r = (r << i) | (r >> (LUA_NBITS - i));
pushunsigned(L, trim(r));
return 1;
}
static int b_lrot (lua_State *L) {
return b_rot(L, luaL_checkinteger(L, 2));
}
static int b_rrot (lua_State *L) {
return b_rot(L, -luaL_checkinteger(L, 2));
}
/*
** get field and width arguments for field-manipulation functions,
** checking whether they are valid.
** ('luaL_error' called without 'return' to avoid later warnings about
** 'width' being used uninitialized.)
*/
static int fieldargs (lua_State *L, int farg, int *width) {
lua_Integer f = luaL_checkinteger(L, farg);
lua_Integer w = luaL_optinteger(L, farg + 1, 1);
luaL_argcheck(L, 0 <= f, farg, "field cannot be negative");
luaL_argcheck(L, 0 < w, farg + 1, "width must be positive");
if (f + w > LUA_NBITS)
luaL_error(L, "trying to access non-existent bits");
*width = (int)w;
return (int)f;
}
static int b_extract (lua_State *L) {
int w;
lua_Unsigned r = trim(checkunsigned(L, 1));
int f = fieldargs(L, 2, &w);
r = (r >> f) & mask(w);
pushunsigned(L, r);
return 1;
}
static int b_replace (lua_State *L) {
int w;
lua_Unsigned r = trim(checkunsigned(L, 1));
lua_Unsigned v = trim(checkunsigned(L, 2));
int f = fieldargs(L, 3, &w);
lua_Unsigned m = mask(w);
r = (r & ~(m << f)) | ((v & m) << f);
pushunsigned(L, r);
return 1;
}
static const luaL_Reg bitlib[] = {
{"arshift", b_arshift},
{"band", b_and},
{"bnot", b_not},
{"bor", b_or},
{"bxor", b_xor},
{"btest", b_test},
{"extract", b_extract},
{"lrotate", b_lrot},
{"lshift", b_lshift},
{"replace", b_replace},
{"rrotate", b_rrot},
{"rshift", b_rshift},
{NULL, NULL}
};
LUAMOD_API int luaopen_bit32 (lua_State *L) {
luaL_newlib(L, bitlib);
return 1;
}
#else /* }{ */
LUAMOD_API int luaopen_bit32 (lua_State *L) {
return luaL_error(L, "library 'bit32' has been deprecated");
}
#endif /* } */

1199
deps/lua/lcode.c vendored Normal file

File diff suppressed because it is too large Load Diff

88
deps/lua/lcode.h vendored Normal file
View File

@@ -0,0 +1,88 @@
/*
** $Id: lcode.h,v 1.64 2016/01/05 16:22:37 roberto Exp $
** Code generator for Lua
** See Copyright Notice in lua.h
*/
#ifndef lcode_h
#define lcode_h
#include "llex.h"
#include "lobject.h"
#include "lopcodes.h"
#include "lparser.h"
/*
** Marks the end of a patch list. It is an invalid value both as an absolute
** address, and as a list link (would link an element to itself).
*/
#define NO_JUMP (-1)
/*
** grep "ORDER OPR" if you change these enums (ORDER OP)
*/
typedef enum BinOpr {
OPR_ADD, OPR_SUB, OPR_MUL, OPR_MOD, OPR_POW,
OPR_DIV,
OPR_IDIV,
OPR_BAND, OPR_BOR, OPR_BXOR,
OPR_SHL, OPR_SHR,
OPR_CONCAT,
OPR_EQ, OPR_LT, OPR_LE,
OPR_NE, OPR_GT, OPR_GE,
OPR_AND, OPR_OR,
OPR_NOBINOPR
} BinOpr;
typedef enum UnOpr { OPR_MINUS, OPR_BNOT, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr;
/* get (pointer to) instruction of given 'expdesc' */
#define getinstruction(fs,e) ((fs)->f->code[(e)->u.info])
#define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx)
#define luaK_setmultret(fs,e) luaK_setreturns(fs, e, LUA_MULTRET)
#define luaK_jumpto(fs,t) luaK_patchlist(fs, luaK_jump(fs), t)
LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx);
LUAI_FUNC int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C);
LUAI_FUNC int luaK_codek (FuncState *fs, int reg, int k);
LUAI_FUNC void luaK_fixline (FuncState *fs, int line);
LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n);
LUAI_FUNC void luaK_reserveregs (FuncState *fs, int n);
LUAI_FUNC void luaK_checkstack (FuncState *fs, int n);
LUAI_FUNC int luaK_stringK (FuncState *fs, TString *s);
LUAI_FUNC int luaK_intK (FuncState *fs, lua_Integer n);
LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e);
LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e);
LUAI_FUNC void luaK_exp2anyregup (FuncState *fs, expdesc *e);
LUAI_FUNC void luaK_exp2nextreg (FuncState *fs, expdesc *e);
LUAI_FUNC void luaK_exp2val (FuncState *fs, expdesc *e);
LUAI_FUNC int luaK_exp2RK (FuncState *fs, expdesc *e);
LUAI_FUNC void luaK_self (FuncState *fs, expdesc *e, expdesc *key);
LUAI_FUNC void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k);
LUAI_FUNC void luaK_goiftrue (FuncState *fs, expdesc *e);
LUAI_FUNC void luaK_goiffalse (FuncState *fs, expdesc *e);
LUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e);
LUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults);
LUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e);
LUAI_FUNC int luaK_jump (FuncState *fs);
LUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret);
LUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target);
LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list);
LUAI_FUNC void luaK_patchclose (FuncState *fs, int list, int level);
LUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2);
LUAI_FUNC int luaK_getlabel (FuncState *fs);
LUAI_FUNC void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v, int line);
LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v);
LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1,
expdesc *v2, int line);
LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore);
#endif

168
deps/lua/lcorolib.c vendored Normal file
View File

@@ -0,0 +1,168 @@
/*
** $Id: lcorolib.c,v 1.10 2016/04/11 19:19:55 roberto Exp $
** Coroutine Library
** See Copyright Notice in lua.h
*/
#define lcorolib_c
#define LUA_LIB
#include "lprefix.h"
#include <stdlib.h>
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
static lua_State *getco (lua_State *L) {
lua_State *co = lua_tothread(L, 1);
luaL_argcheck(L, co, 1, "thread expected");
return co;
}
static int auxresume (lua_State *L, lua_State *co, int narg) {
int status;
if (!lua_checkstack(co, narg)) {
lua_pushliteral(L, "too many arguments to resume");
return -1; /* error flag */
}
if (lua_status(co) == LUA_OK && lua_gettop(co) == 0) {
lua_pushliteral(L, "cannot resume dead coroutine");
return -1; /* error flag */
}
lua_xmove(L, co, narg);
status = lua_resume(co, L, narg);
if (status == LUA_OK || status == LUA_YIELD) {
int nres = lua_gettop(co);
if (!lua_checkstack(L, nres + 1)) {
lua_pop(co, nres); /* remove results anyway */
lua_pushliteral(L, "too many results to resume");
return -1; /* error flag */
}
lua_xmove(co, L, nres); /* move yielded values */
return nres;
}
else {
lua_xmove(co, L, 1); /* move error message */
return -1; /* error flag */
}
}
static int luaB_coresume (lua_State *L) {
lua_State *co = getco(L);
int r;
r = auxresume(L, co, lua_gettop(L) - 1);
if (r < 0) {
lua_pushboolean(L, 0);
lua_insert(L, -2);
return 2; /* return false + error message */
}
else {
lua_pushboolean(L, 1);
lua_insert(L, -(r + 1));
return r + 1; /* return true + 'resume' returns */
}
}
static int luaB_auxwrap (lua_State *L) {
lua_State *co = lua_tothread(L, lua_upvalueindex(1));
int r = auxresume(L, co, lua_gettop(L));
if (r < 0) {
if (lua_type(L, -1) == LUA_TSTRING) { /* error object is a string? */
luaL_where(L, 1); /* add extra info */
lua_insert(L, -2);
lua_concat(L, 2);
}
return lua_error(L); /* propagate error */
}
return r;
}
static int luaB_cocreate (lua_State *L) {
lua_State *NL;
luaL_checktype(L, 1, LUA_TFUNCTION);
NL = lua_newthread(L);
lua_pushvalue(L, 1); /* move function to top */
lua_xmove(L, NL, 1); /* move function from L to NL */
return 1;
}
static int luaB_cowrap (lua_State *L) {
luaB_cocreate(L);
lua_pushcclosure(L, luaB_auxwrap, 1);
return 1;
}
static int luaB_yield (lua_State *L) {
return lua_yield(L, lua_gettop(L));
}
static int luaB_costatus (lua_State *L) {
lua_State *co = getco(L);
if (L == co) lua_pushliteral(L, "running");
else {
switch (lua_status(co)) {
case LUA_YIELD:
lua_pushliteral(L, "suspended");
break;
case LUA_OK: {
lua_Debug ar;
if (lua_getstack(co, 0, &ar) > 0) /* does it have frames? */
lua_pushliteral(L, "normal"); /* it is running */
else if (lua_gettop(co) == 0)
lua_pushliteral(L, "dead");
else
lua_pushliteral(L, "suspended"); /* initial state */
break;
}
default: /* some error occurred */
lua_pushliteral(L, "dead");
break;
}
}
return 1;
}
static int luaB_yieldable (lua_State *L) {
lua_pushboolean(L, lua_isyieldable(L));
return 1;
}
static int luaB_corunning (lua_State *L) {
int ismain = lua_pushthread(L);
lua_pushboolean(L, ismain);
return 2;
}
static const luaL_Reg co_funcs[] = {
{"create", luaB_cocreate},
{"resume", luaB_coresume},
{"running", luaB_corunning},
{"status", luaB_costatus},
{"wrap", luaB_cowrap},
{"yield", luaB_yield},
{"isyieldable", luaB_yieldable},
{NULL, NULL}
};
LUAMOD_API int luaopen_coroutine (lua_State *L) {
luaL_newlib(L, co_funcs);
return 1;
}

55
deps/lua/lctype.c vendored Normal file
View File

@@ -0,0 +1,55 @@
/*
** $Id: lctype.c,v 1.12 2014/11/02 19:19:04 roberto Exp $
** 'ctype' functions for Lua
** See Copyright Notice in lua.h
*/
#define lctype_c
#define LUA_CORE
#include "lprefix.h"
#include "lctype.h"
#if !LUA_USE_CTYPE /* { */
#include <limits.h>
LUAI_DDEF const lu_byte luai_ctype_[UCHAR_MAX + 2] = {
0x00, /* EOZ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0. */
0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 1. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0c, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, /* 2. */
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, /* 3. */
0x16, 0x16, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x05, /* 4. */
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 5. */
0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x05,
0x04, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x05, /* 6. */
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 7. */
0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 8. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 9. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* a. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* b. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* c. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* d. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* e. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* f. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
#endif /* } */

95
deps/lua/lctype.h vendored Normal file
View File

@@ -0,0 +1,95 @@
/*
** $Id: lctype.h,v 1.12 2011/07/15 12:50:29 roberto Exp $
** 'ctype' functions for Lua
** See Copyright Notice in lua.h
*/
#ifndef lctype_h
#define lctype_h
#include "lua.h"
/*
** WARNING: the functions defined here do not necessarily correspond
** to the similar functions in the standard C ctype.h. They are
** optimized for the specific needs of Lua
*/
#if !defined(LUA_USE_CTYPE)
#if 'A' == 65 && '0' == 48
/* ASCII case: can use its own tables; faster and fixed */
#define LUA_USE_CTYPE 0
#else
/* must use standard C ctype */
#define LUA_USE_CTYPE 1
#endif
#endif
#if !LUA_USE_CTYPE /* { */
#include <limits.h>
#include "llimits.h"
#define ALPHABIT 0
#define DIGITBIT 1
#define PRINTBIT 2
#define SPACEBIT 3
#define XDIGITBIT 4
#define MASK(B) (1 << (B))
/*
** add 1 to char to allow index -1 (EOZ)
*/
#define testprop(c,p) (luai_ctype_[(c)+1] & (p))
/*
** 'lalpha' (Lua alphabetic) and 'lalnum' (Lua alphanumeric) both include '_'
*/
#define lislalpha(c) testprop(c, MASK(ALPHABIT))
#define lislalnum(c) testprop(c, (MASK(ALPHABIT) | MASK(DIGITBIT)))
#define lisdigit(c) testprop(c, MASK(DIGITBIT))
#define lisspace(c) testprop(c, MASK(SPACEBIT))
#define lisprint(c) testprop(c, MASK(PRINTBIT))
#define lisxdigit(c) testprop(c, MASK(XDIGITBIT))
/*
** this 'ltolower' only works for alphabetic characters
*/
#define ltolower(c) ((c) | ('A' ^ 'a'))
/* two more entries for 0 and -1 (EOZ) */
LUAI_DDEC const lu_byte luai_ctype_[UCHAR_MAX + 2];
#else /* }{ */
/*
** use standard C ctypes
*/
#include <ctype.h>
#define lislalpha(c) (isalpha(c) || (c) == '_')
#define lislalnum(c) (isalnum(c) || (c) == '_')
#define lisdigit(c) (isdigit(c))
#define lisspace(c) (isspace(c))
#define lisprint(c) (isprint(c))
#define lisxdigit(c) (isxdigit(c))
#define ltolower(c) (tolower(c))
#endif /* } */
#endif

456
deps/lua/ldblib.c vendored Normal file
View File

@@ -0,0 +1,456 @@
/*
** $Id: ldblib.c,v 1.151 2015/11/23 11:29:43 roberto Exp $
** Interface from Lua to its debug API
** See Copyright Notice in lua.h
*/
#define ldblib_c
#define LUA_LIB
#include "lprefix.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
/*
** The hook table at registry[&HOOKKEY] maps threads to their current
** hook function. (We only need the unique address of 'HOOKKEY'.)
*/
static const int HOOKKEY = 0;
/*
** If L1 != L, L1 can be in any state, and therefore there are no
** guarantees about its stack space; any push in L1 must be
** checked.
*/
static void checkstack (lua_State *L, lua_State *L1, int n) {
if (L != L1 && !lua_checkstack(L1, n))
luaL_error(L, "stack overflow");
}
static int db_getregistry (lua_State *L) {
lua_pushvalue(L, LUA_REGISTRYINDEX);
return 1;
}
static int db_getmetatable (lua_State *L) {
luaL_checkany(L, 1);
if (!lua_getmetatable(L, 1)) {
lua_pushnil(L); /* no metatable */
}
return 1;
}
static int db_setmetatable (lua_State *L) {
int t = lua_type(L, 2);
luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,
"nil or table expected");
lua_settop(L, 2);
lua_setmetatable(L, 1);
return 1; /* return 1st argument */
}
static int db_getuservalue (lua_State *L) {
if (lua_type(L, 1) != LUA_TUSERDATA)
lua_pushnil(L);
else
lua_getuservalue(L, 1);
return 1;
}
static int db_setuservalue (lua_State *L) {
luaL_checktype(L, 1, LUA_TUSERDATA);
luaL_checkany(L, 2);
lua_settop(L, 2);
lua_setuservalue(L, 1);
return 1;
}
/*
** Auxiliary function used by several library functions: check for
** an optional thread as function's first argument and set 'arg' with
** 1 if this argument is present (so that functions can skip it to
** access their other arguments)
*/
static lua_State *getthread (lua_State *L, int *arg) {
if (lua_isthread(L, 1)) {
*arg = 1;
return lua_tothread(L, 1);
}
else {
*arg = 0;
return L; /* function will operate over current thread */
}
}
/*
** Variations of 'lua_settable', used by 'db_getinfo' to put results
** from 'lua_getinfo' into result table. Key is always a string;
** value can be a string, an int, or a boolean.
*/
static void settabss (lua_State *L, const char *k, const char *v) {
lua_pushstring(L, v);
lua_setfield(L, -2, k);
}
static void settabsi (lua_State *L, const char *k, int v) {
lua_pushinteger(L, v);
lua_setfield(L, -2, k);
}
static void settabsb (lua_State *L, const char *k, int v) {
lua_pushboolean(L, v);
lua_setfield(L, -2, k);
}
/*
** In function 'db_getinfo', the call to 'lua_getinfo' may push
** results on the stack; later it creates the result table to put
** these objects. Function 'treatstackoption' puts the result from
** 'lua_getinfo' on top of the result table so that it can call
** 'lua_setfield'.
*/
static void treatstackoption (lua_State *L, lua_State *L1, const char *fname) {
if (L == L1)
lua_rotate(L, -2, 1); /* exchange object and table */
else
lua_xmove(L1, L, 1); /* move object to the "main" stack */
lua_setfield(L, -2, fname); /* put object into table */
}
/*
** Calls 'lua_getinfo' and collects all results in a new table.
** L1 needs stack space for an optional input (function) plus
** two optional outputs (function and line table) from function
** 'lua_getinfo'.
*/
static int db_getinfo (lua_State *L) {
lua_Debug ar;
int arg;
lua_State *L1 = getthread(L, &arg);
const char *options = luaL_optstring(L, arg+2, "flnStu");
checkstack(L, L1, 3);
if (lua_isfunction(L, arg + 1)) { /* info about a function? */
options = lua_pushfstring(L, ">%s", options); /* add '>' to 'options' */
lua_pushvalue(L, arg + 1); /* move function to 'L1' stack */
lua_xmove(L, L1, 1);
}
else { /* stack level */
if (!lua_getstack(L1, (int)luaL_checkinteger(L, arg + 1), &ar)) {
lua_pushnil(L); /* level out of range */
return 1;
}
}
if (!lua_getinfo(L1, options, &ar))
return luaL_argerror(L, arg+2, "invalid option");
lua_newtable(L); /* table to collect results */
if (strchr(options, 'S')) {
settabss(L, "source", ar.source);
settabss(L, "short_src", ar.short_src);
settabsi(L, "linedefined", ar.linedefined);
settabsi(L, "lastlinedefined", ar.lastlinedefined);
settabss(L, "what", ar.what);
}
if (strchr(options, 'l'))
settabsi(L, "currentline", ar.currentline);
if (strchr(options, 'u')) {
settabsi(L, "nups", ar.nups);
settabsi(L, "nparams", ar.nparams);
settabsb(L, "isvararg", ar.isvararg);
}
if (strchr(options, 'n')) {
settabss(L, "name", ar.name);
settabss(L, "namewhat", ar.namewhat);
}
if (strchr(options, 't'))
settabsb(L, "istailcall", ar.istailcall);
if (strchr(options, 'L'))
treatstackoption(L, L1, "activelines");
if (strchr(options, 'f'))
treatstackoption(L, L1, "func");
return 1; /* return table */
}
static int db_getlocal (lua_State *L) {
int arg;
lua_State *L1 = getthread(L, &arg);
lua_Debug ar;
const char *name;
int nvar = (int)luaL_checkinteger(L, arg + 2); /* local-variable index */
if (lua_isfunction(L, arg + 1)) { /* function argument? */
lua_pushvalue(L, arg + 1); /* push function */
lua_pushstring(L, lua_getlocal(L, NULL, nvar)); /* push local name */
return 1; /* return only name (there is no value) */
}
else { /* stack-level argument */
int level = (int)luaL_checkinteger(L, arg + 1);
if (!lua_getstack(L1, level, &ar)) /* out of range? */
return luaL_argerror(L, arg+1, "level out of range");
checkstack(L, L1, 1);
name = lua_getlocal(L1, &ar, nvar);
if (name) {
lua_xmove(L1, L, 1); /* move local value */
lua_pushstring(L, name); /* push name */
lua_rotate(L, -2, 1); /* re-order */
return 2;
}
else {
lua_pushnil(L); /* no name (nor value) */
return 1;
}
}
}
static int db_setlocal (lua_State *L) {
int arg;
const char *name;
lua_State *L1 = getthread(L, &arg);
lua_Debug ar;
int level = (int)luaL_checkinteger(L, arg + 1);
int nvar = (int)luaL_checkinteger(L, arg + 2);
if (!lua_getstack(L1, level, &ar)) /* out of range? */
return luaL_argerror(L, arg+1, "level out of range");
luaL_checkany(L, arg+3);
lua_settop(L, arg+3);
checkstack(L, L1, 1);
lua_xmove(L, L1, 1);
name = lua_setlocal(L1, &ar, nvar);
if (name == NULL)
lua_pop(L1, 1); /* pop value (if not popped by 'lua_setlocal') */
lua_pushstring(L, name);
return 1;
}
/*
** get (if 'get' is true) or set an upvalue from a closure
*/
static int auxupvalue (lua_State *L, int get) {
const char *name;
int n = (int)luaL_checkinteger(L, 2); /* upvalue index */
luaL_checktype(L, 1, LUA_TFUNCTION); /* closure */
name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n);
if (name == NULL) return 0;
lua_pushstring(L, name);
lua_insert(L, -(get+1)); /* no-op if get is false */
return get + 1;
}
static int db_getupvalue (lua_State *L) {
return auxupvalue(L, 1);
}
static int db_setupvalue (lua_State *L) {
luaL_checkany(L, 3);
return auxupvalue(L, 0);
}
/*
** Check whether a given upvalue from a given closure exists and
** returns its index
*/
static int checkupval (lua_State *L, int argf, int argnup) {
int nup = (int)luaL_checkinteger(L, argnup); /* upvalue index */
luaL_checktype(L, argf, LUA_TFUNCTION); /* closure */
luaL_argcheck(L, (lua_getupvalue(L, argf, nup) != NULL), argnup,
"invalid upvalue index");
return nup;
}
static int db_upvalueid (lua_State *L) {
int n = checkupval(L, 1, 2);
lua_pushlightuserdata(L, lua_upvalueid(L, 1, n));
return 1;
}
static int db_upvaluejoin (lua_State *L) {
int n1 = checkupval(L, 1, 2);
int n2 = checkupval(L, 3, 4);
luaL_argcheck(L, !lua_iscfunction(L, 1), 1, "Lua function expected");
luaL_argcheck(L, !lua_iscfunction(L, 3), 3, "Lua function expected");
lua_upvaluejoin(L, 1, n1, 3, n2);
return 0;
}
/*
** Call hook function registered at hook table for the current
** thread (if there is one)
*/
static void hookf (lua_State *L, lua_Debug *ar) {
static const char *const hooknames[] =
{"call", "return", "line", "count", "tail call"};
lua_rawgetp(L, LUA_REGISTRYINDEX, &HOOKKEY);
lua_pushthread(L);
if (lua_rawget(L, -2) == LUA_TFUNCTION) { /* is there a hook function? */
lua_pushstring(L, hooknames[(int)ar->event]); /* push event name */
if (ar->currentline >= 0)
lua_pushinteger(L, ar->currentline); /* push current line */
else lua_pushnil(L);
lua_assert(lua_getinfo(L, "lS", ar));
lua_call(L, 2, 0); /* call hook function */
}
}
/*
** Convert a string mask (for 'sethook') into a bit mask
*/
static int makemask (const char *smask, int count) {
int mask = 0;
if (strchr(smask, 'c')) mask |= LUA_MASKCALL;
if (strchr(smask, 'r')) mask |= LUA_MASKRET;
if (strchr(smask, 'l')) mask |= LUA_MASKLINE;
if (count > 0) mask |= LUA_MASKCOUNT;
return mask;
}
/*
** Convert a bit mask (for 'gethook') into a string mask
*/
static char *unmakemask (int mask, char *smask) {
int i = 0;
if (mask & LUA_MASKCALL) smask[i++] = 'c';
if (mask & LUA_MASKRET) smask[i++] = 'r';
if (mask & LUA_MASKLINE) smask[i++] = 'l';
smask[i] = '\0';
return smask;
}
static int db_sethook (lua_State *L) {
int arg, mask, count;
lua_Hook func;
lua_State *L1 = getthread(L, &arg);
if (lua_isnoneornil(L, arg+1)) { /* no hook? */
lua_settop(L, arg+1);
func = NULL; mask = 0; count = 0; /* turn off hooks */
}
else {
const char *smask = luaL_checkstring(L, arg+2);
luaL_checktype(L, arg+1, LUA_TFUNCTION);
count = (int)luaL_optinteger(L, arg + 3, 0);
func = hookf; mask = makemask(smask, count);
}
if (lua_rawgetp(L, LUA_REGISTRYINDEX, &HOOKKEY) == LUA_TNIL) {
lua_createtable(L, 0, 2); /* create a hook table */
lua_pushvalue(L, -1);
lua_rawsetp(L, LUA_REGISTRYINDEX, &HOOKKEY); /* set it in position */
lua_pushstring(L, "k");
lua_setfield(L, -2, "__mode"); /** hooktable.__mode = "k" */
lua_pushvalue(L, -1);
lua_setmetatable(L, -2); /* setmetatable(hooktable) = hooktable */
}
checkstack(L, L1, 1);
lua_pushthread(L1); lua_xmove(L1, L, 1); /* key (thread) */
lua_pushvalue(L, arg + 1); /* value (hook function) */
lua_rawset(L, -3); /* hooktable[L1] = new Lua hook */
lua_sethook(L1, func, mask, count);
return 0;
}
static int db_gethook (lua_State *L) {
int arg;
lua_State *L1 = getthread(L, &arg);
char buff[5];
int mask = lua_gethookmask(L1);
lua_Hook hook = lua_gethook(L1);
if (hook == NULL) /* no hook? */
lua_pushnil(L);
else if (hook != hookf) /* external hook? */
lua_pushliteral(L, "external hook");
else { /* hook table must exist */
lua_rawgetp(L, LUA_REGISTRYINDEX, &HOOKKEY);
checkstack(L, L1, 1);
lua_pushthread(L1); lua_xmove(L1, L, 1);
lua_rawget(L, -2); /* 1st result = hooktable[L1] */
lua_remove(L, -2); /* remove hook table */
}
lua_pushstring(L, unmakemask(mask, buff)); /* 2nd result = mask */
lua_pushinteger(L, lua_gethookcount(L1)); /* 3rd result = count */
return 3;
}
static int db_debug (lua_State *L) {
for (;;) {
char buffer[250];
lua_writestringerror("%s", "lua_debug> ");
if (fgets(buffer, sizeof(buffer), stdin) == 0 ||
strcmp(buffer, "cont\n") == 0)
return 0;
if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") ||
lua_pcall(L, 0, 0, 0))
lua_writestringerror("%s\n", lua_tostring(L, -1));
lua_settop(L, 0); /* remove eventual returns */
}
}
static int db_traceback (lua_State *L) {
int arg;
lua_State *L1 = getthread(L, &arg);
const char *msg = lua_tostring(L, arg + 1);
if (msg == NULL && !lua_isnoneornil(L, arg + 1)) /* non-string 'msg'? */
lua_pushvalue(L, arg + 1); /* return it untouched */
else {
int level = (int)luaL_optinteger(L, arg + 2, (L == L1) ? 1 : 0);
luaL_traceback(L, L1, msg, level);
}
return 1;
}
static const luaL_Reg dblib[] = {
{"debug", db_debug},
{"getuservalue", db_getuservalue},
{"gethook", db_gethook},
{"getinfo", db_getinfo},
{"getlocal", db_getlocal},
{"getregistry", db_getregistry},
{"getmetatable", db_getmetatable},
{"getupvalue", db_getupvalue},
{"upvaluejoin", db_upvaluejoin},
{"upvalueid", db_upvalueid},
{"setuservalue", db_setuservalue},
{"sethook", db_sethook},
{"setlocal", db_setlocal},
{"setmetatable", db_setmetatable},
{"setupvalue", db_setupvalue},
{"traceback", db_traceback},
{NULL, NULL}
};
LUAMOD_API int luaopen_debug (lua_State *L) {
luaL_newlib(L, dblib);
return 1;
}

679
deps/lua/ldebug.c vendored Normal file
View File

@@ -0,0 +1,679 @@
/*
** $Id: ldebug.c,v 2.120 2016/03/31 19:01:21 roberto Exp $
** Debug Interface
** See Copyright Notice in lua.h
*/
#define ldebug_c
#define LUA_CORE
#include "lprefix.h"
#include <stdarg.h>
#include <stddef.h>
#include <string.h>
#include "lua.h"
#include "lapi.h"
#include "lcode.h"
#include "ldebug.h"
#include "ldo.h"
#include "lfunc.h"
#include "lobject.h"
#include "lopcodes.h"
#include "lstate.h"
#include "lstring.h"
#include "ltable.h"
#include "ltm.h"
#include "lvm.h"
#define noLuaClosure(f) ((f) == NULL || (f)->c.tt == LUA_TCCL)
/* Active Lua function (given call info) */
#define ci_func(ci) (clLvalue((ci)->func))
static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name);
static int currentpc (CallInfo *ci) {
lua_assert(isLua(ci));
return pcRel(ci->u.l.savedpc, ci_func(ci)->p);
}
static int currentline (CallInfo *ci) {
return getfuncline(ci_func(ci)->p, currentpc(ci));
}
/*
** If function yielded, its 'func' can be in the 'extra' field. The
** next function restores 'func' to its correct value for debugging
** purposes. (It exchanges 'func' and 'extra'; so, when called again,
** after debugging, it also "re-restores" ** 'func' to its altered value.
*/
static void swapextra (lua_State *L) {
if (L->status == LUA_YIELD) {
CallInfo *ci = L->ci; /* get function that yielded */
StkId temp = ci->func; /* exchange its 'func' and 'extra' values */
ci->func = restorestack(L, ci->extra);
ci->extra = savestack(L, temp);
}
}
/*
** This function can be called asynchronously (e.g. during a signal).
** Fields 'oldpc', 'basehookcount', and 'hookcount' (set by
** 'resethookcount') are for debug only, and it is no problem if they
** get arbitrary values (causes at most one wrong hook call). 'hookmask'
** is an atomic value. We assume that pointers are atomic too (e.g., gcc
** ensures that for all platforms where it runs). Moreover, 'hook' is
** always checked before being called (see 'luaD_hook').
*/
LUA_API void lua_sethook (lua_State *L, lua_Hook func, int mask, int count) {
if (func == NULL || mask == 0) { /* turn off hooks? */
mask = 0;
func = NULL;
}
if (isLua(L->ci))
L->oldpc = L->ci->u.l.savedpc;
L->hook = func;
L->basehookcount = count;
resethookcount(L);
L->hookmask = cast_byte(mask);
}
LUA_API lua_Hook lua_gethook (lua_State *L) {
return L->hook;
}
LUA_API int lua_gethookmask (lua_State *L) {
return L->hookmask;
}
LUA_API int lua_gethookcount (lua_State *L) {
return L->basehookcount;
}
LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) {
int status;
CallInfo *ci;
if (level < 0) return 0; /* invalid (negative) level */
lua_lock(L);
for (ci = L->ci; level > 0 && ci != &L->base_ci; ci = ci->previous)
level--;
if (level == 0 && ci != &L->base_ci) { /* level found? */
status = 1;
ar->i_ci = ci;
}
else status = 0; /* no such level */
lua_unlock(L);
return status;
}
static const char *upvalname (Proto *p, int uv) {
TString *s = check_exp(uv < p->sizeupvalues, p->upvalues[uv].name);
if (s == NULL) return "?";
else return getstr(s);
}
static const char *findvararg (CallInfo *ci, int n, StkId *pos) {
int nparams = clLvalue(ci->func)->p->numparams;
if (n >= cast_int(ci->u.l.base - ci->func) - nparams)
return NULL; /* no such vararg */
else {
*pos = ci->func + nparams + n;
return "(*vararg)"; /* generic name for any vararg */
}
}
static const char *findlocal (lua_State *L, CallInfo *ci, int n,
StkId *pos) {
const char *name = NULL;
StkId base;
if (isLua(ci)) {
if (n < 0) /* access to vararg values? */
return findvararg(ci, -n, pos);
else {
base = ci->u.l.base;
name = luaF_getlocalname(ci_func(ci)->p, n, currentpc(ci));
}
}
else
base = ci->func + 1;
if (name == NULL) { /* no 'standard' name? */
StkId limit = (ci == L->ci) ? L->top : ci->next->func;
if (limit - base >= n && n > 0) /* is 'n' inside 'ci' stack? */
name = "(*temporary)"; /* generic name for any valid slot */
else
return NULL; /* no name */
}
*pos = base + (n - 1);
return name;
}
LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) {
const char *name;
lua_lock(L);
swapextra(L);
if (ar == NULL) { /* information about non-active function? */
if (!isLfunction(L->top - 1)) /* not a Lua function? */
name = NULL;
else /* consider live variables at function start (parameters) */
name = luaF_getlocalname(clLvalue(L->top - 1)->p, n, 0);
}
else { /* active function; get information through 'ar' */
StkId pos = NULL; /* to avoid warnings */
name = findlocal(L, ar->i_ci, n, &pos);
if (name) {
setobj2s(L, L->top, pos);
api_incr_top(L);
}
}
swapextra(L);
lua_unlock(L);
return name;
}
LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) {
StkId pos = NULL; /* to avoid warnings */
const char *name;
lua_lock(L);
swapextra(L);
name = findlocal(L, ar->i_ci, n, &pos);
if (name) {
setobjs2s(L, pos, L->top - 1);
L->top--; /* pop value */
}
swapextra(L);
lua_unlock(L);
return name;
}
static void funcinfo (lua_Debug *ar, Closure *cl) {
if (noLuaClosure(cl)) {
ar->source = "=[C]";
ar->linedefined = -1;
ar->lastlinedefined = -1;
ar->what = "C";
}
else {
Proto *p = cl->l.p;
ar->source = p->source ? getstr(p->source) : "=?";
ar->linedefined = p->linedefined;
ar->lastlinedefined = p->lastlinedefined;
ar->what = (ar->linedefined == 0) ? "main" : "Lua";
}
luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE);
}
static void collectvalidlines (lua_State *L, Closure *f) {
if (noLuaClosure(f)) {
setnilvalue(L->top);
api_incr_top(L);
}
else {
int i;
TValue v;
int *lineinfo = f->l.p->lineinfo;
Table *t = luaH_new(L); /* new table to store active lines */
sethvalue(L, L->top, t); /* push it on stack */
api_incr_top(L);
setbvalue(&v, 1); /* boolean 'true' to be the value of all indices */
for (i = 0; i < f->l.p->sizelineinfo; i++) /* for all lines with code */
luaH_setint(L, t, lineinfo[i], &v); /* table[line] = true */
}
}
static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar,
Closure *f, CallInfo *ci) {
int status = 1;
for (; *what; what++) {
switch (*what) {
case 'S': {
funcinfo(ar, f);
break;
}
case 'l': {
ar->currentline = (ci && isLua(ci)) ? currentline(ci) : -1;
break;
}
case 'u': {
ar->nups = (f == NULL) ? 0 : f->c.nupvalues;
if (noLuaClosure(f)) {
ar->isvararg = 1;
ar->nparams = 0;
}
else {
ar->isvararg = f->l.p->is_vararg;
ar->nparams = f->l.p->numparams;
}
break;
}
case 't': {
ar->istailcall = (ci) ? ci->callstatus & CIST_TAIL : 0;
break;
}
case 'n': {
/* calling function is a known Lua function? */
if (ci && !(ci->callstatus & CIST_TAIL) && isLua(ci->previous))
ar->namewhat = getfuncname(L, ci->previous, &ar->name);
else
ar->namewhat = NULL;
if (ar->namewhat == NULL) {
ar->namewhat = ""; /* not found */
ar->name = NULL;
}
break;
}
case 'L':
case 'f': /* handled by lua_getinfo */
break;
default: status = 0; /* invalid option */
}
}
return status;
}
LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) {
int status;
Closure *cl;
CallInfo *ci;
StkId func;
lua_lock(L);
swapextra(L);
if (*what == '>') {
ci = NULL;
func = L->top - 1;
api_check(L, ttisfunction(func), "function expected");
what++; /* skip the '>' */
L->top--; /* pop function */
}
else {
ci = ar->i_ci;
func = ci->func;
lua_assert(ttisfunction(ci->func));
}
cl = ttisclosure(func) ? clvalue(func) : NULL;
status = auxgetinfo(L, what, ar, cl, ci);
if (strchr(what, 'f')) {
setobjs2s(L, L->top, func);
api_incr_top(L);
}
swapextra(L); /* correct before option 'L', which can raise a mem. error */
if (strchr(what, 'L'))
collectvalidlines(L, cl);
lua_unlock(L);
return status;
}
/*
** {======================================================
** Symbolic Execution
** =======================================================
*/
static const char *getobjname (Proto *p, int lastpc, int reg,
const char **name);
/*
** find a "name" for the RK value 'c'
*/
static void kname (Proto *p, int pc, int c, const char **name) {
if (ISK(c)) { /* is 'c' a constant? */
TValue *kvalue = &p->k[INDEXK(c)];
if (ttisstring(kvalue)) { /* literal constant? */
*name = svalue(kvalue); /* it is its own name */
return;
}
/* else no reasonable name found */
}
else { /* 'c' is a register */
const char *what = getobjname(p, pc, c, name); /* search for 'c' */
if (what && *what == 'c') { /* found a constant name? */
return; /* 'name' already filled */
}
/* else no reasonable name found */
}
*name = "?"; /* no reasonable name found */
}
static int filterpc (int pc, int jmptarget) {
if (pc < jmptarget) /* is code conditional (inside a jump)? */
return -1; /* cannot know who sets that register */
else return pc; /* current position sets that register */
}
/*
** try to find last instruction before 'lastpc' that modified register 'reg'
*/
static int findsetreg (Proto *p, int lastpc, int reg) {
int pc;
int setreg = -1; /* keep last instruction that changed 'reg' */
int jmptarget = 0; /* any code before this address is conditional */
for (pc = 0; pc < lastpc; pc++) {
Instruction i = p->code[pc];
OpCode op = GET_OPCODE(i);
int a = GETARG_A(i);
switch (op) {
case OP_LOADNIL: {
int b = GETARG_B(i);
if (a <= reg && reg <= a + b) /* set registers from 'a' to 'a+b' */
setreg = filterpc(pc, jmptarget);
break;
}
case OP_TFORCALL: {
if (reg >= a + 2) /* affect all regs above its base */
setreg = filterpc(pc, jmptarget);
break;
}
case OP_CALL:
case OP_TAILCALL: {
if (reg >= a) /* affect all registers above base */
setreg = filterpc(pc, jmptarget);
break;
}
case OP_JMP: {
int b = GETARG_sBx(i);
int dest = pc + 1 + b;
/* jump is forward and do not skip 'lastpc'? */
if (pc < dest && dest <= lastpc) {
if (dest > jmptarget)
jmptarget = dest; /* update 'jmptarget' */
}
break;
}
default:
if (testAMode(op) && reg == a) /* any instruction that set A */
setreg = filterpc(pc, jmptarget);
break;
}
}
return setreg;
}
static const char *getobjname (Proto *p, int lastpc, int reg,
const char **name) {
int pc;
*name = luaF_getlocalname(p, reg + 1, lastpc);
if (*name) /* is a local? */
return "local";
/* else try symbolic execution */
pc = findsetreg(p, lastpc, reg);
if (pc != -1) { /* could find instruction? */
Instruction i = p->code[pc];
OpCode op = GET_OPCODE(i);
switch (op) {
case OP_MOVE: {
int b = GETARG_B(i); /* move from 'b' to 'a' */
if (b < GETARG_A(i))
return getobjname(p, pc, b, name); /* get name for 'b' */
break;
}
case OP_GETTABUP:
case OP_GETTABLE: {
int k = GETARG_C(i); /* key index */
int t = GETARG_B(i); /* table index */
const char *vn = (op == OP_GETTABLE) /* name of indexed variable */
? luaF_getlocalname(p, t + 1, pc)
: upvalname(p, t);
kname(p, pc, k, name);
return (vn && strcmp(vn, LUA_ENV) == 0) ? "global" : "field";
}
case OP_GETUPVAL: {
*name = upvalname(p, GETARG_B(i));
return "upvalue";
}
case OP_LOADK:
case OP_LOADKX: {
int b = (op == OP_LOADK) ? GETARG_Bx(i)
: GETARG_Ax(p->code[pc + 1]);
if (ttisstring(&p->k[b])) {
*name = svalue(&p->k[b]);
return "constant";
}
break;
}
case OP_SELF: {
int k = GETARG_C(i); /* key index */
kname(p, pc, k, name);
return "method";
}
default: break; /* go through to return NULL */
}
}
return NULL; /* could not find reasonable name */
}
static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) {
TMS tm = (TMS)0; /* to avoid warnings */
Proto *p = ci_func(ci)->p; /* calling function */
int pc = currentpc(ci); /* calling instruction index */
Instruction i = p->code[pc]; /* calling instruction */
if (ci->callstatus & CIST_HOOKED) { /* was it called inside a hook? */
*name = "?";
return "hook";
}
switch (GET_OPCODE(i)) {
case OP_CALL:
case OP_TAILCALL: /* get function name */
return getobjname(p, pc, GETARG_A(i), name);
case OP_TFORCALL: { /* for iterator */
*name = "for iterator";
return "for iterator";
}
/* all other instructions can call only through metamethods */
case OP_SELF: case OP_GETTABUP: case OP_GETTABLE:
tm = TM_INDEX;
break;
case OP_SETTABUP: case OP_SETTABLE:
tm = TM_NEWINDEX;
break;
case OP_ADD: case OP_SUB: case OP_MUL: case OP_MOD:
case OP_POW: case OP_DIV: case OP_IDIV: case OP_BAND:
case OP_BOR: case OP_BXOR: case OP_SHL: case OP_SHR: {
int offset = cast_int(GET_OPCODE(i)) - cast_int(OP_ADD); /* ORDER OP */
tm = cast(TMS, offset + cast_int(TM_ADD)); /* ORDER TM */
break;
}
case OP_UNM: tm = TM_UNM; break;
case OP_BNOT: tm = TM_BNOT; break;
case OP_LEN: tm = TM_LEN; break;
case OP_CONCAT: tm = TM_CONCAT; break;
case OP_EQ: tm = TM_EQ; break;
case OP_LT: tm = TM_LT; break;
case OP_LE: tm = TM_LE; break;
default: lua_assert(0); /* other instructions cannot call a function */
}
*name = getstr(G(L)->tmname[tm]);
return "metamethod";
}
/* }====================================================== */
/*
** The subtraction of two potentially unrelated pointers is
** not ISO C, but it should not crash a program; the subsequent
** checks are ISO C and ensure a correct result.
*/
static int isinstack (CallInfo *ci, const TValue *o) {
ptrdiff_t i = o - ci->u.l.base;
return (0 <= i && i < (ci->top - ci->u.l.base) && ci->u.l.base + i == o);
}
/*
** Checks whether value 'o' came from an upvalue. (That can only happen
** with instructions OP_GETTABUP/OP_SETTABUP, which operate directly on
** upvalues.)
*/
static const char *getupvalname (CallInfo *ci, const TValue *o,
const char **name) {
LClosure *c = ci_func(ci);
int i;
for (i = 0; i < c->nupvalues; i++) {
if (c->upvals[i]->v == o) {
*name = upvalname(c->p, i);
return "upvalue";
}
}
return NULL;
}
static const char *varinfo (lua_State *L, const TValue *o) {
const char *name = NULL; /* to avoid warnings */
CallInfo *ci = L->ci;
const char *kind = NULL;
if (isLua(ci)) {
kind = getupvalname(ci, o, &name); /* check whether 'o' is an upvalue */
if (!kind && isinstack(ci, o)) /* no? try a register */
kind = getobjname(ci_func(ci)->p, currentpc(ci),
cast_int(o - ci->u.l.base), &name);
}
return (kind) ? luaO_pushfstring(L, " (%s '%s')", kind, name) : "";
}
l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *op) {
const char *t = luaT_objtypename(L, o);
luaG_runerror(L, "attempt to %s a %s value%s", op, t, varinfo(L, o));
}
l_noret luaG_concaterror (lua_State *L, const TValue *p1, const TValue *p2) {
if (ttisstring(p1) || cvt2str(p1)) p1 = p2;
luaG_typeerror(L, p1, "concatenate");
}
l_noret luaG_opinterror (lua_State *L, const TValue *p1,
const TValue *p2, const char *msg) {
lua_Number temp;
if (!tonumber(p1, &temp)) /* first operand is wrong? */
p2 = p1; /* now second is wrong */
luaG_typeerror(L, p2, msg);
}
/*
** Error when both values are convertible to numbers, but not to integers
*/
l_noret luaG_tointerror (lua_State *L, const TValue *p1, const TValue *p2) {
lua_Integer temp;
if (!tointeger(p1, &temp))
p2 = p1;
luaG_runerror(L, "number%s has no integer representation", varinfo(L, p2));
}
l_noret luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) {
const char *t1 = luaT_objtypename(L, p1);
const char *t2 = luaT_objtypename(L, p2);
if (strcmp(t1, t2) == 0)
luaG_runerror(L, "attempt to compare two %s values", t1);
else
luaG_runerror(L, "attempt to compare %s with %s", t1, t2);
}
/* add src:line information to 'msg' */
const char *luaG_addinfo (lua_State *L, const char *msg, TString *src,
int line) {
char buff[LUA_IDSIZE];
if (src)
luaO_chunkid(buff, getstr(src), LUA_IDSIZE);
else { /* no source available; use "?" instead */
buff[0] = '?'; buff[1] = '\0';
}
return luaO_pushfstring(L, "%s:%d: %s", buff, line, msg);
}
l_noret luaG_errormsg (lua_State *L) {
if (L->errfunc != 0) { /* is there an error handling function? */
StkId errfunc = restorestack(L, L->errfunc);
setobjs2s(L, L->top, L->top - 1); /* move argument */
setobjs2s(L, L->top - 1, errfunc); /* push function */
L->top++; /* assume EXTRA_STACK */
luaD_callnoyield(L, L->top - 2, 1); /* call it */
}
luaD_throw(L, LUA_ERRRUN);
}
l_noret luaG_runerror (lua_State *L, const char *fmt, ...) {
CallInfo *ci = L->ci;
const char *msg;
va_list argp;
va_start(argp, fmt);
msg = luaO_pushvfstring(L, fmt, argp); /* format message */
va_end(argp);
if (isLua(ci)) /* if Lua function, add source:line information */
luaG_addinfo(L, msg, ci_func(ci)->p->source, currentline(ci));
luaG_errormsg(L);
}
void luaG_traceexec (lua_State *L) {
CallInfo *ci = L->ci;
lu_byte mask = L->hookmask;
int counthook = (--L->hookcount == 0 && (mask & LUA_MASKCOUNT));
if (counthook)
resethookcount(L); /* reset count */
else if (!(mask & LUA_MASKLINE))
return; /* no line hook and count != 0; nothing to be done */
if (ci->callstatus & CIST_HOOKYIELD) { /* called hook last time? */
ci->callstatus &= ~CIST_HOOKYIELD; /* erase mark */
return; /* do not call hook again (VM yielded, so it did not move) */
}
if (counthook)
luaD_hook(L, LUA_HOOKCOUNT, -1); /* call count hook */
if (mask & LUA_MASKLINE) {
Proto *p = ci_func(ci)->p;
int npc = pcRel(ci->u.l.savedpc, p);
int newline = getfuncline(p, npc);
if (npc == 0 || /* call linehook when enter a new function, */
ci->u.l.savedpc <= L->oldpc || /* when jump back (loop), or when */
newline != getfuncline(p, pcRel(L->oldpc, p))) /* enter a new line */
luaD_hook(L, LUA_HOOKLINE, newline); /* call line hook */
}
L->oldpc = ci->u.l.savedpc;
if (L->status == LUA_YIELD) { /* did hook yield? */
if (counthook)
L->hookcount = 1; /* undo decrement to zero */
ci->u.l.savedpc--; /* undo increment (resume will increment it again) */
ci->callstatus |= CIST_HOOKYIELD; /* mark that it yielded */
ci->func = L->top - 1; /* protect stack below results */
luaD_throw(L, LUA_YIELD);
}
}

39
deps/lua/ldebug.h vendored Normal file
View File

@@ -0,0 +1,39 @@
/*
** $Id: ldebug.h,v 2.14 2015/05/22 17:45:56 roberto Exp $
** Auxiliary functions from Debug Interface module
** See Copyright Notice in lua.h
*/
#ifndef ldebug_h
#define ldebug_h
#include "lstate.h"
#define pcRel(pc, p) (cast(int, (pc) - (p)->code) - 1)
#define getfuncline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : -1)
#define resethookcount(L) (L->hookcount = L->basehookcount)
LUAI_FUNC l_noret luaG_typeerror (lua_State *L, const TValue *o,
const char *opname);
LUAI_FUNC l_noret luaG_concaterror (lua_State *L, const TValue *p1,
const TValue *p2);
LUAI_FUNC l_noret luaG_opinterror (lua_State *L, const TValue *p1,
const TValue *p2,
const char *msg);
LUAI_FUNC l_noret luaG_tointerror (lua_State *L, const TValue *p1,
const TValue *p2);
LUAI_FUNC l_noret luaG_ordererror (lua_State *L, const TValue *p1,
const TValue *p2);
LUAI_FUNC l_noret luaG_runerror (lua_State *L, const char *fmt, ...);
LUAI_FUNC const char *luaG_addinfo (lua_State *L, const char *msg,
TString *src, int line);
LUAI_FUNC l_noret luaG_errormsg (lua_State *L);
LUAI_FUNC void luaG_traceexec (lua_State *L);
#endif

800
deps/lua/ldo.c vendored Normal file
View File

@@ -0,0 +1,800 @@
/*
** $Id: ldo.c,v 2.151 2015/12/16 16:40:07 roberto Exp $
** Stack and Call structure of Lua
** See Copyright Notice in lua.h
*/
#define ldo_c
#define LUA_CORE
#include "lprefix.h"
#include <setjmp.h>
#include <stdlib.h>
#include <string.h>
#include "lua.h"
#include "lapi.h"
#include "ldebug.h"
#include "ldo.h"
#include "lfunc.h"
#include "lgc.h"
#include "lmem.h"
#include "lobject.h"
#include "lopcodes.h"
#include "lparser.h"
#include "lstate.h"
#include "lstring.h"
#include "ltable.h"
#include "ltm.h"
#include "lundump.h"
#include "lvm.h"
#include "lzio.h"
#define errorstatus(s) ((s) > LUA_YIELD)
/*
** {======================================================
** Error-recovery functions
** =======================================================
*/
/*
** LUAI_THROW/LUAI_TRY define how Lua does exception handling. By
** default, Lua handles errors with exceptions when compiling as
** C++ code, with _longjmp/_setjmp when asked to use them, and with
** longjmp/setjmp otherwise.
*/
#if !defined(LUAI_THROW) /* { */
#if defined(__cplusplus) && !defined(LUA_USE_LONGJMP) /* { */
/* C++ exceptions */
#define LUAI_THROW(L,c) throw(c)
#define LUAI_TRY(L,c,a) \
try { a } catch(...) { if ((c)->status == 0) (c)->status = -1; }
#define luai_jmpbuf int /* dummy variable */
#elif defined(LUA_USE_POSIX) /* }{ */
/* in POSIX, try _longjmp/_setjmp (more efficient) */
#define LUAI_THROW(L,c) _longjmp((c)->b, 1)
#define LUAI_TRY(L,c,a) if (_setjmp((c)->b) == 0) { a }
#define luai_jmpbuf jmp_buf
#else /* }{ */
/* ISO C handling with long jumps */
#define LUAI_THROW(L,c) longjmp((c)->b, 1)
#define LUAI_TRY(L,c,a) if (setjmp((c)->b) == 0) { a }
#define luai_jmpbuf jmp_buf
#endif /* } */
#endif /* } */
/* chain list of long jump buffers */
struct lua_longjmp {
struct lua_longjmp *previous;
luai_jmpbuf b;
volatile int status; /* error code */
};
static void seterrorobj (lua_State *L, int errcode, StkId oldtop) {
switch (errcode) {
case LUA_ERRMEM: { /* memory error? */
setsvalue2s(L, oldtop, G(L)->memerrmsg); /* reuse preregistered msg. */
break;
}
case LUA_ERRERR: {
setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling"));
break;
}
default: {
setobjs2s(L, oldtop, L->top - 1); /* error message on current top */
break;
}
}
L->top = oldtop + 1;
}
l_noret luaD_throw (lua_State *L, int errcode) {
if (L->errorJmp) { /* thread has an error handler? */
L->errorJmp->status = errcode; /* set status */
LUAI_THROW(L, L->errorJmp); /* jump to it */
}
else { /* thread has no error handler */
global_State *g = G(L);
L->status = cast_byte(errcode); /* mark it as dead */
if (g->mainthread->errorJmp) { /* main thread has a handler? */
setobjs2s(L, g->mainthread->top++, L->top - 1); /* copy error obj. */
luaD_throw(g->mainthread, errcode); /* re-throw in main thread */
}
else { /* no handler at all; abort */
if (g->panic) { /* panic function? */
seterrorobj(L, errcode, L->top); /* assume EXTRA_STACK */
if (L->ci->top < L->top)
L->ci->top = L->top; /* pushing msg. can break this invariant */
lua_unlock(L);
g->panic(L); /* call panic function (last chance to jump out) */
}
abort();
}
}
}
int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) {
unsigned short oldnCcalls = L->nCcalls;
struct lua_longjmp lj;
lj.status = LUA_OK;
lj.previous = L->errorJmp; /* chain new error handler */
L->errorJmp = &lj;
LUAI_TRY(L, &lj,
(*f)(L, ud);
);
L->errorJmp = lj.previous; /* restore old error handler */
L->nCcalls = oldnCcalls;
return lj.status;
}
/* }====================================================== */
/*
** {==================================================================
** Stack reallocation
** ===================================================================
*/
static void correctstack (lua_State *L, TValue *oldstack) {
CallInfo *ci;
UpVal *up;
L->top = (L->top - oldstack) + L->stack;
for (up = L->openupval; up != NULL; up = up->u.open.next)
up->v = (up->v - oldstack) + L->stack;
for (ci = L->ci; ci != NULL; ci = ci->previous) {
ci->top = (ci->top - oldstack) + L->stack;
ci->func = (ci->func - oldstack) + L->stack;
if (isLua(ci))
ci->u.l.base = (ci->u.l.base - oldstack) + L->stack;
}
}
/* some space for error handling */
#define ERRORSTACKSIZE (LUAI_MAXSTACK + 200)
void luaD_reallocstack (lua_State *L, int newsize) {
TValue *oldstack = L->stack;
int lim = L->stacksize;
lua_assert(newsize <= LUAI_MAXSTACK || newsize == ERRORSTACKSIZE);
lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK);
luaM_reallocvector(L, L->stack, L->stacksize, newsize, TValue);
for (; lim < newsize; lim++)
setnilvalue(L->stack + lim); /* erase new segment */
L->stacksize = newsize;
L->stack_last = L->stack + newsize - EXTRA_STACK;
correctstack(L, oldstack);
}
void luaD_growstack (lua_State *L, int n) {
int size = L->stacksize;
if (size > LUAI_MAXSTACK) /* error after extra size? */
luaD_throw(L, LUA_ERRERR);
else {
int needed = cast_int(L->top - L->stack) + n + EXTRA_STACK;
int newsize = 2 * size;
if (newsize > LUAI_MAXSTACK) newsize = LUAI_MAXSTACK;
if (newsize < needed) newsize = needed;
if (newsize > LUAI_MAXSTACK) { /* stack overflow? */
luaD_reallocstack(L, ERRORSTACKSIZE);
luaG_runerror(L, "stack overflow");
}
else
luaD_reallocstack(L, newsize);
}
}
static int stackinuse (lua_State *L) {
CallInfo *ci;
StkId lim = L->top;
for (ci = L->ci; ci != NULL; ci = ci->previous) {
lua_assert(ci->top <= L->stack_last);
if (lim < ci->top) lim = ci->top;
}
return cast_int(lim - L->stack) + 1; /* part of stack in use */
}
void luaD_shrinkstack (lua_State *L) {
int inuse = stackinuse(L);
int goodsize = inuse + (inuse / 8) + 2*EXTRA_STACK;
if (goodsize > LUAI_MAXSTACK) goodsize = LUAI_MAXSTACK;
if (L->stacksize > LUAI_MAXSTACK) /* was handling stack overflow? */
luaE_freeCI(L); /* free all CIs (list grew because of an error) */
else
luaE_shrinkCI(L); /* shrink list */
if (inuse <= LUAI_MAXSTACK && /* not handling stack overflow? */
goodsize < L->stacksize) /* trying to shrink? */
luaD_reallocstack(L, goodsize); /* shrink it */
else
condmovestack(L,,); /* don't change stack (change only for debugging) */
}
void luaD_inctop (lua_State *L) {
luaD_checkstack(L, 1);
L->top++;
}
/* }================================================================== */
/*
** Call a hook for the given event. Make sure there is a hook to be
** called. (Both 'L->hook' and 'L->hookmask', which triggers this
** function, can be changed asynchronously by signals.)
*/
void luaD_hook (lua_State *L, int event, int line) {
lua_Hook hook = L->hook;
if (hook && L->allowhook) { /* make sure there is a hook */
CallInfo *ci = L->ci;
ptrdiff_t top = savestack(L, L->top);
ptrdiff_t ci_top = savestack(L, ci->top);
lua_Debug ar;
ar.event = event;
ar.currentline = line;
ar.i_ci = ci;
luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */
ci->top = L->top + LUA_MINSTACK;
lua_assert(ci->top <= L->stack_last);
L->allowhook = 0; /* cannot call hooks inside a hook */
ci->callstatus |= CIST_HOOKED;
lua_unlock(L);
(*hook)(L, &ar);
lua_lock(L);
lua_assert(!L->allowhook);
L->allowhook = 1;
ci->top = restorestack(L, ci_top);
L->top = restorestack(L, top);
ci->callstatus &= ~CIST_HOOKED;
}
}
static void callhook (lua_State *L, CallInfo *ci) {
int hook = LUA_HOOKCALL;
ci->u.l.savedpc++; /* hooks assume 'pc' is already incremented */
if (isLua(ci->previous) &&
GET_OPCODE(*(ci->previous->u.l.savedpc - 1)) == OP_TAILCALL) {
ci->callstatus |= CIST_TAIL;
hook = LUA_HOOKTAILCALL;
}
luaD_hook(L, hook, -1);
ci->u.l.savedpc--; /* correct 'pc' */
}
static StkId adjust_varargs (lua_State *L, Proto *p, int actual) {
int i;
int nfixargs = p->numparams;
StkId base, fixed;
/* move fixed parameters to final position */
fixed = L->top - actual; /* first fixed argument */
base = L->top; /* final position of first argument */
for (i = 0; i < nfixargs && i < actual; i++) {
setobjs2s(L, L->top++, fixed + i);
setnilvalue(fixed + i); /* erase original copy (for GC) */
}
for (; i < nfixargs; i++)
setnilvalue(L->top++); /* complete missing arguments */
return base;
}
/*
** Check whether __call metafield of 'func' is a function. If so, put
** it in stack below original 'func' so that 'luaD_precall' can call
** it. Raise an error if __call metafield is not a function.
*/
static void tryfuncTM (lua_State *L, StkId func) {
const TValue *tm = luaT_gettmbyobj(L, func, TM_CALL);
StkId p;
if (!ttisfunction(tm))
luaG_typeerror(L, func, "call");
/* Open a hole inside the stack at 'func' */
for (p = L->top; p > func; p--)
setobjs2s(L, p, p-1);
L->top++; /* slot ensured by caller */
setobj2s(L, func, tm); /* tag method is the new function to be called */
}
#define next_ci(L) (L->ci = (L->ci->next ? L->ci->next : luaE_extendCI(L)))
/* macro to check stack size, preserving 'p' */
#define checkstackp(L,n,p) \
luaD_checkstackaux(L, n, \
ptrdiff_t t__ = savestack(L, p); /* save 'p' */ \
luaC_checkGC(L), /* stack grow uses memory */ \
p = restorestack(L, t__)) /* 'pos' part: restore 'p' */
/*
** Prepares a function call: checks the stack, creates a new CallInfo
** entry, fills in the relevant information, calls hook if needed.
** If function is a C function, does the call, too. (Otherwise, leave
** the execution ('luaV_execute') to the caller, to allow stackless
** calls.) Returns true iff function has been executed (C function).
*/
int luaD_precall (lua_State *L, StkId func, int nresults) {
lua_CFunction f;
CallInfo *ci;
switch (ttype(func)) {
case LUA_TCCL: /* C closure */
f = clCvalue(func)->f;
goto Cfunc;
case LUA_TLCF: /* light C function */
f = fvalue(func);
Cfunc: {
int n; /* number of returns */
checkstackp(L, LUA_MINSTACK, func); /* ensure minimum stack size */
ci = next_ci(L); /* now 'enter' new function */
ci->nresults = nresults;
ci->func = func;
ci->top = L->top + LUA_MINSTACK;
lua_assert(ci->top <= L->stack_last);
ci->callstatus = 0;
if (L->hookmask & LUA_MASKCALL)
luaD_hook(L, LUA_HOOKCALL, -1);
lua_unlock(L);
n = (*f)(L); /* do the actual call */
lua_lock(L);
api_checknelems(L, n);
luaD_poscall(L, ci, L->top - n, n);
return 1;
}
case LUA_TLCL: { /* Lua function: prepare its call */
StkId base;
Proto *p = clLvalue(func)->p;
int n = cast_int(L->top - func) - 1; /* number of real arguments */
int fsize = p->maxstacksize; /* frame size */
checkstackp(L, fsize, func);
if (p->is_vararg != 1) { /* do not use vararg? */
for (; n < p->numparams; n++)
setnilvalue(L->top++); /* complete missing arguments */
base = func + 1;
}
else
base = adjust_varargs(L, p, n);
ci = next_ci(L); /* now 'enter' new function */
ci->nresults = nresults;
ci->func = func;
ci->u.l.base = base;
L->top = ci->top = base + fsize;
lua_assert(ci->top <= L->stack_last);
ci->u.l.savedpc = p->code; /* starting point */
ci->callstatus = CIST_LUA;
if (L->hookmask & LUA_MASKCALL)
callhook(L, ci);
return 0;
}
default: { /* not a function */
checkstackp(L, 1, func); /* ensure space for metamethod */
tryfuncTM(L, func); /* try to get '__call' metamethod */
return luaD_precall(L, func, nresults); /* now it must be a function */
}
}
}
/*
** Given 'nres' results at 'firstResult', move 'wanted' of them to 'res'.
** Handle most typical cases (zero results for commands, one result for
** expressions, multiple results for tail calls/single parameters)
** separated.
*/
static int moveresults (lua_State *L, const TValue *firstResult, StkId res,
int nres, int wanted) {
switch (wanted) { /* handle typical cases separately */
case 0: break; /* nothing to move */
case 1: { /* one result needed */
if (nres == 0) /* no results? */
firstResult = luaO_nilobject; /* adjust with nil */
setobjs2s(L, res, firstResult); /* move it to proper place */
break;
}
case LUA_MULTRET: {
int i;
for (i = 0; i < nres; i++) /* move all results to correct place */
setobjs2s(L, res + i, firstResult + i);
L->top = res + nres;
return 0; /* wanted == LUA_MULTRET */
}
default: {
int i;
if (wanted <= nres) { /* enough results? */
for (i = 0; i < wanted; i++) /* move wanted results to correct place */
setobjs2s(L, res + i, firstResult + i);
}
else { /* not enough results; use all of them plus nils */
for (i = 0; i < nres; i++) /* move all results to correct place */
setobjs2s(L, res + i, firstResult + i);
for (; i < wanted; i++) /* complete wanted number of results */
setnilvalue(res + i);
}
break;
}
}
L->top = res + wanted; /* top points after the last result */
return 1;
}
/*
** Finishes a function call: calls hook if necessary, removes CallInfo,
** moves current number of results to proper place; returns 0 iff call
** wanted multiple (variable number of) results.
*/
int luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, int nres) {
StkId res;
int wanted = ci->nresults;
if (L->hookmask & (LUA_MASKRET | LUA_MASKLINE)) {
if (L->hookmask & LUA_MASKRET) {
ptrdiff_t fr = savestack(L, firstResult); /* hook may change stack */
luaD_hook(L, LUA_HOOKRET, -1);
firstResult = restorestack(L, fr);
}
L->oldpc = ci->previous->u.l.savedpc; /* 'oldpc' for caller function */
}
res = ci->func; /* res == final position of 1st result */
L->ci = ci->previous; /* back to caller */
/* move results to proper place */
return moveresults(L, firstResult, res, nres, wanted);
}
/*
** Check appropriate error for stack overflow ("regular" overflow or
** overflow while handling stack overflow). If 'nCalls' is larger than
** LUAI_MAXCCALLS (which means it is handling a "regular" overflow) but
** smaller than 9/8 of LUAI_MAXCCALLS, does not report an error (to
** allow overflow handling to work)
*/
static void stackerror (lua_State *L) {
if (L->nCcalls == LUAI_MAXCCALLS)
luaG_runerror(L, "C stack overflow");
else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3)))
luaD_throw(L, LUA_ERRERR); /* error while handing stack error */
}
/*
** Call a function (C or Lua). The function to be called is at *func.
** The arguments are on the stack, right after the function.
** When returns, all the results are on the stack, starting at the original
** function position.
*/
void luaD_call (lua_State *L, StkId func, int nResults) {
if (++L->nCcalls >= LUAI_MAXCCALLS)
stackerror(L);
if (!luaD_precall(L, func, nResults)) /* is a Lua function? */
luaV_execute(L); /* call it */
L->nCcalls--;
}
/*
** Similar to 'luaD_call', but does not allow yields during the call
*/
void luaD_callnoyield (lua_State *L, StkId func, int nResults) {
L->nny++;
luaD_call(L, func, nResults);
L->nny--;
}
/*
** Completes the execution of an interrupted C function, calling its
** continuation function.
*/
static void finishCcall (lua_State *L, int status) {
CallInfo *ci = L->ci;
int n;
/* must have a continuation and must be able to call it */
lua_assert(ci->u.c.k != NULL && L->nny == 0);
/* error status can only happen in a protected call */
lua_assert((ci->callstatus & CIST_YPCALL) || status == LUA_YIELD);
if (ci->callstatus & CIST_YPCALL) { /* was inside a pcall? */
ci->callstatus &= ~CIST_YPCALL; /* finish 'lua_pcall' */
L->errfunc = ci->u.c.old_errfunc;
}
/* finish 'lua_callk'/'lua_pcall'; CIST_YPCALL and 'errfunc' already
handled */
adjustresults(L, ci->nresults);
/* call continuation function */
lua_unlock(L);
n = (*ci->u.c.k)(L, status, ci->u.c.ctx);
lua_lock(L);
api_checknelems(L, n);
/* finish 'luaD_precall' */
luaD_poscall(L, ci, L->top - n, n);
}
/*
** Executes "full continuation" (everything in the stack) of a
** previously interrupted coroutine until the stack is empty (or another
** interruption long-jumps out of the loop). If the coroutine is
** recovering from an error, 'ud' points to the error status, which must
** be passed to the first continuation function (otherwise the default
** status is LUA_YIELD).
*/
static void unroll (lua_State *L, void *ud) {
if (ud != NULL) /* error status? */
finishCcall(L, *(int *)ud); /* finish 'lua_pcallk' callee */
while (L->ci != &L->base_ci) { /* something in the stack */
if (!isLua(L->ci)) /* C function? */
finishCcall(L, LUA_YIELD); /* complete its execution */
else { /* Lua function */
luaV_finishOp(L); /* finish interrupted instruction */
luaV_execute(L); /* execute down to higher C 'boundary' */
}
}
}
/*
** Try to find a suspended protected call (a "recover point") for the
** given thread.
*/
static CallInfo *findpcall (lua_State *L) {
CallInfo *ci;
for (ci = L->ci; ci != NULL; ci = ci->previous) { /* search for a pcall */
if (ci->callstatus & CIST_YPCALL)
return ci;
}
return NULL; /* no pending pcall */
}
/*
** Recovers from an error in a coroutine. Finds a recover point (if
** there is one) and completes the execution of the interrupted
** 'luaD_pcall'. If there is no recover point, returns zero.
*/
static int recover (lua_State *L, int status) {
StkId oldtop;
CallInfo *ci = findpcall(L);
if (ci == NULL) return 0; /* no recovery point */
/* "finish" luaD_pcall */
oldtop = restorestack(L, ci->extra);
luaF_close(L, oldtop);
seterrorobj(L, status, oldtop);
L->ci = ci;
L->allowhook = getoah(ci->callstatus); /* restore original 'allowhook' */
L->nny = 0; /* should be zero to be yieldable */
luaD_shrinkstack(L);
L->errfunc = ci->u.c.old_errfunc;
return 1; /* continue running the coroutine */
}
/*
** signal an error in the call to 'resume', not in the execution of the
** coroutine itself. (Such errors should not be handled by any coroutine
** error handler and should not kill the coroutine.)
*/
static l_noret resume_error (lua_State *L, const char *msg, StkId firstArg) {
L->top = firstArg; /* remove args from the stack */
setsvalue2s(L, L->top, luaS_new(L, msg)); /* push error message */
api_incr_top(L);
luaD_throw(L, -1); /* jump back to 'lua_resume' */
}
/*
** Do the work for 'lua_resume' in protected mode. Most of the work
** depends on the status of the coroutine: initial state, suspended
** inside a hook, or regularly suspended (optionally with a continuation
** function), plus erroneous cases: non-suspended coroutine or dead
** coroutine.
*/
static void resume (lua_State *L, void *ud) {
int nCcalls = L->nCcalls;
int n = *(cast(int*, ud)); /* number of arguments */
StkId firstArg = L->top - n; /* first argument */
CallInfo *ci = L->ci;
if (nCcalls >= LUAI_MAXCCALLS)
resume_error(L, "C stack overflow", firstArg);
if (L->status == LUA_OK) { /* may be starting a coroutine */
if (ci != &L->base_ci) /* not in base level? */
resume_error(L, "cannot resume non-suspended coroutine", firstArg);
/* coroutine is in base level; start running it */
if (!luaD_precall(L, firstArg - 1, LUA_MULTRET)) /* Lua function? */
luaV_execute(L); /* call it */
}
else if (L->status != LUA_YIELD)
resume_error(L, "cannot resume dead coroutine", firstArg);
else { /* resuming from previous yield */
L->status = LUA_OK; /* mark that it is running (again) */
ci->func = restorestack(L, ci->extra);
if (isLua(ci)) /* yielded inside a hook? */
luaV_execute(L); /* just continue running Lua code */
else { /* 'common' yield */
if (ci->u.c.k != NULL) { /* does it have a continuation function? */
lua_unlock(L);
n = (*ci->u.c.k)(L, LUA_YIELD, ci->u.c.ctx); /* call continuation */
lua_lock(L);
api_checknelems(L, n);
firstArg = L->top - n; /* yield results come from continuation */
}
luaD_poscall(L, ci, firstArg, n); /* finish 'luaD_precall' */
}
unroll(L, NULL); /* run continuation */
}
lua_assert(nCcalls == L->nCcalls);
}
LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs) {
int status;
unsigned short oldnny = L->nny; /* save "number of non-yieldable" calls */
lua_lock(L);
luai_userstateresume(L, nargs);
L->nCcalls = (from) ? from->nCcalls + 1 : 1;
L->nny = 0; /* allow yields */
api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs);
status = luaD_rawrunprotected(L, resume, &nargs);
if (status == -1) /* error calling 'lua_resume'? */
status = LUA_ERRRUN;
else { /* continue running after recoverable errors */
while (errorstatus(status) && recover(L, status)) {
/* unroll continuation */
status = luaD_rawrunprotected(L, unroll, &status);
}
if (errorstatus(status)) { /* unrecoverable error? */
L->status = cast_byte(status); /* mark thread as 'dead' */
seterrorobj(L, status, L->top); /* push error message */
L->ci->top = L->top;
}
else lua_assert(status == L->status); /* normal end or yield */
}
L->nny = oldnny; /* restore 'nny' */
L->nCcalls--;
lua_assert(L->nCcalls == ((from) ? from->nCcalls : 0));
lua_unlock(L);
return status;
}
LUA_API int lua_isyieldable (lua_State *L) {
return (L->nny == 0);
}
LUA_API int lua_yieldk (lua_State *L, int nresults, lua_KContext ctx,
lua_KFunction k) {
CallInfo *ci = L->ci;
luai_userstateyield(L, nresults);
lua_lock(L);
api_checknelems(L, nresults);
if (L->nny > 0) {
if (L != G(L)->mainthread)
luaG_runerror(L, "attempt to yield across a C-call boundary");
else
luaG_runerror(L, "attempt to yield from outside a coroutine");
}
L->status = LUA_YIELD;
ci->extra = savestack(L, ci->func); /* save current 'func' */
if (isLua(ci)) { /* inside a hook? */
api_check(L, k == NULL, "hooks cannot continue after yielding");
}
else {
if ((ci->u.c.k = k) != NULL) /* is there a continuation? */
ci->u.c.ctx = ctx; /* save context */
ci->func = L->top - nresults - 1; /* protect stack below results */
luaD_throw(L, LUA_YIELD);
}
lua_assert(ci->callstatus & CIST_HOOKED); /* must be inside a hook */
lua_unlock(L);
return 0; /* return to 'luaD_hook' */
}
int luaD_pcall (lua_State *L, Pfunc func, void *u,
ptrdiff_t old_top, ptrdiff_t ef) {
int status;
CallInfo *old_ci = L->ci;
lu_byte old_allowhooks = L->allowhook;
unsigned short old_nny = L->nny;
ptrdiff_t old_errfunc = L->errfunc;
L->errfunc = ef;
status = luaD_rawrunprotected(L, func, u);
if (status != LUA_OK) { /* an error occurred? */
StkId oldtop = restorestack(L, old_top);
luaF_close(L, oldtop); /* close possible pending closures */
seterrorobj(L, status, oldtop);
L->ci = old_ci;
L->allowhook = old_allowhooks;
L->nny = old_nny;
luaD_shrinkstack(L);
}
L->errfunc = old_errfunc;
return status;
}
/*
** Execute a protected parser.
*/
struct SParser { /* data to 'f_parser' */
ZIO *z;
Mbuffer buff; /* dynamic structure used by the scanner */
Dyndata dyd; /* dynamic structures used by the parser */
const char *mode;
const char *name;
};
static void checkmode (lua_State *L, const char *mode, const char *x) {
if (mode && strchr(mode, x[0]) == NULL) {
luaO_pushfstring(L,
"attempt to load a %s chunk (mode is '%s')", x, mode);
luaD_throw(L, LUA_ERRSYNTAX);
}
}
static void f_parser (lua_State *L, void *ud) {
LClosure *cl;
struct SParser *p = cast(struct SParser *, ud);
int c = zgetc(p->z); /* read first character */
if (c == LUA_SIGNATURE[0]) {
checkmode(L, p->mode, "binary");
cl = luaU_undump(L, p->z, p->name);
}
else {
checkmode(L, p->mode, "text");
cl = luaY_parser(L, p->z, &p->buff, &p->dyd, p->name, c);
}
lua_assert(cl->nupvalues == cl->p->sizeupvalues);
luaF_initupvals(L, cl);
}
int luaD_protectedparser (lua_State *L, ZIO *z, const char *name,
const char *mode) {
struct SParser p;
int status;
L->nny++; /* cannot yield during parsing */
p.z = z; p.name = name; p.mode = mode;
p.dyd.actvar.arr = NULL; p.dyd.actvar.size = 0;
p.dyd.gt.arr = NULL; p.dyd.gt.size = 0;
p.dyd.label.arr = NULL; p.dyd.label.size = 0;
luaZ_initbuffer(L, &p.buff);
status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc);
luaZ_freebuffer(L, &p.buff);
luaM_freearray(L, p.dyd.actvar.arr, p.dyd.actvar.size);
luaM_freearray(L, p.dyd.gt.arr, p.dyd.gt.size);
luaM_freearray(L, p.dyd.label.arr, p.dyd.label.size);
L->nny--;
return status;
}

58
deps/lua/ldo.h vendored Normal file
View File

@@ -0,0 +1,58 @@
/*
** $Id: ldo.h,v 2.29 2015/12/21 13:02:14 roberto Exp $
** Stack and Call structure of Lua
** See Copyright Notice in lua.h
*/
#ifndef ldo_h
#define ldo_h
#include "lobject.h"
#include "lstate.h"
#include "lzio.h"
/*
** Macro to check stack size and grow stack if needed. Parameters
** 'pre'/'pos' allow the macro to preserve a pointer into the
** stack across reallocations, doing the work only when needed.
** 'condmovestack' is used in heavy tests to force a stack reallocation
** at every check.
*/
#define luaD_checkstackaux(L,n,pre,pos) \
if (L->stack_last - L->top <= (n)) \
{ pre; luaD_growstack(L, n); pos; } else { condmovestack(L,pre,pos); }
/* In general, 'pre'/'pos' are empty (nothing to save) */
#define luaD_checkstack(L,n) luaD_checkstackaux(L,n,(void)0,(void)0)
#define savestack(L,p) ((char *)(p) - (char *)L->stack)
#define restorestack(L,n) ((TValue *)((char *)L->stack + (n)))
/* type of protected functions, to be ran by 'runprotected' */
typedef void (*Pfunc) (lua_State *L, void *ud);
LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name,
const char *mode);
LUAI_FUNC void luaD_hook (lua_State *L, int event, int line);
LUAI_FUNC int luaD_precall (lua_State *L, StkId func, int nresults);
LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults);
LUAI_FUNC void luaD_callnoyield (lua_State *L, StkId func, int nResults);
LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u,
ptrdiff_t oldtop, ptrdiff_t ef);
LUAI_FUNC int luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult,
int nres);
LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize);
LUAI_FUNC void luaD_growstack (lua_State *L, int n);
LUAI_FUNC void luaD_shrinkstack (lua_State *L);
LUAI_FUNC void luaD_inctop (lua_State *L);
LUAI_FUNC l_noret luaD_throw (lua_State *L, int errcode);
LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud);
#endif

215
deps/lua/ldump.c vendored Normal file
View File

@@ -0,0 +1,215 @@
/*
** $Id: ldump.c,v 2.37 2015/10/08 15:53:49 roberto Exp $
** save precompiled Lua chunks
** See Copyright Notice in lua.h
*/
#define ldump_c
#define LUA_CORE
#include "lprefix.h"
#include <stddef.h>
#include "lua.h"
#include "lobject.h"
#include "lstate.h"
#include "lundump.h"
typedef struct {
lua_State *L;
lua_Writer writer;
void *data;
int strip;
int status;
} DumpState;
/*
** All high-level dumps go through DumpVector; you can change it to
** change the endianness of the result
*/
#define DumpVector(v,n,D) DumpBlock(v,(n)*sizeof((v)[0]),D)
#define DumpLiteral(s,D) DumpBlock(s, sizeof(s) - sizeof(char), D)
static void DumpBlock (const void *b, size_t size, DumpState *D) {
if (D->status == 0 && size > 0) {
lua_unlock(D->L);
D->status = (*D->writer)(D->L, b, size, D->data);
lua_lock(D->L);
}
}
#define DumpVar(x,D) DumpVector(&x,1,D)
static void DumpByte (int y, DumpState *D) {
lu_byte x = (lu_byte)y;
DumpVar(x, D);
}
static void DumpInt (int x, DumpState *D) {
DumpVar(x, D);
}
static void DumpNumber (lua_Number x, DumpState *D) {
DumpVar(x, D);
}
static void DumpInteger (lua_Integer x, DumpState *D) {
DumpVar(x, D);
}
static void DumpString (const TString *s, DumpState *D) {
if (s == NULL)
DumpByte(0, D);
else {
size_t size = tsslen(s) + 1; /* include trailing '\0' */
const char *str = getstr(s);
if (size < 0xFF)
DumpByte(cast_int(size), D);
else {
DumpByte(0xFF, D);
DumpVar(size, D);
}
DumpVector(str, size - 1, D); /* no need to save '\0' */
}
}
static void DumpCode (const Proto *f, DumpState *D) {
DumpInt(f->sizecode, D);
DumpVector(f->code, f->sizecode, D);
}
static void DumpFunction(const Proto *f, TString *psource, DumpState *D);
static void DumpConstants (const Proto *f, DumpState *D) {
int i;
int n = f->sizek;
DumpInt(n, D);
for (i = 0; i < n; i++) {
const TValue *o = &f->k[i];
DumpByte(ttype(o), D);
switch (ttype(o)) {
case LUA_TNIL:
break;
case LUA_TBOOLEAN:
DumpByte(bvalue(o), D);
break;
case LUA_TNUMFLT:
DumpNumber(fltvalue(o), D);
break;
case LUA_TNUMINT:
DumpInteger(ivalue(o), D);
break;
case LUA_TSHRSTR:
case LUA_TLNGSTR:
DumpString(tsvalue(o), D);
break;
default:
lua_assert(0);
}
}
}
static void DumpProtos (const Proto *f, DumpState *D) {
int i;
int n = f->sizep;
DumpInt(n, D);
for (i = 0; i < n; i++)
DumpFunction(f->p[i], f->source, D);
}
static void DumpUpvalues (const Proto *f, DumpState *D) {
int i, n = f->sizeupvalues;
DumpInt(n, D);
for (i = 0; i < n; i++) {
DumpByte(f->upvalues[i].instack, D);
DumpByte(f->upvalues[i].idx, D);
}
}
static void DumpDebug (const Proto *f, DumpState *D) {
int i, n;
n = (D->strip) ? 0 : f->sizelineinfo;
DumpInt(n, D);
DumpVector(f->lineinfo, n, D);
n = (D->strip) ? 0 : f->sizelocvars;
DumpInt(n, D);
for (i = 0; i < n; i++) {
DumpString(f->locvars[i].varname, D);
DumpInt(f->locvars[i].startpc, D);
DumpInt(f->locvars[i].endpc, D);
}
n = (D->strip) ? 0 : f->sizeupvalues;
DumpInt(n, D);
for (i = 0; i < n; i++)
DumpString(f->upvalues[i].name, D);
}
static void DumpFunction (const Proto *f, TString *psource, DumpState *D) {
if (D->strip || f->source == psource)
DumpString(NULL, D); /* no debug info or same source as its parent */
else
DumpString(f->source, D);
DumpInt(f->linedefined, D);
DumpInt(f->lastlinedefined, D);
DumpByte(f->numparams, D);
DumpByte(f->is_vararg, D);
DumpByte(f->maxstacksize, D);
DumpCode(f, D);
DumpConstants(f, D);
DumpUpvalues(f, D);
DumpProtos(f, D);
DumpDebug(f, D);
}
static void DumpHeader (DumpState *D) {
DumpLiteral(LUA_SIGNATURE, D);
DumpByte(LUAC_VERSION, D);
DumpByte(LUAC_FORMAT, D);
DumpLiteral(LUAC_DATA, D);
DumpByte(sizeof(int), D);
DumpByte(sizeof(size_t), D);
DumpByte(sizeof(Instruction), D);
DumpByte(sizeof(lua_Integer), D);
DumpByte(sizeof(lua_Number), D);
DumpInteger(LUAC_INT, D);
DumpNumber(LUAC_NUM, D);
}
/*
** dump Lua function as precompiled chunk
*/
int luaU_dump(lua_State *L, const Proto *f, lua_Writer w, void *data,
int strip) {
DumpState D;
D.L = L;
D.writer = w;
D.data = data;
D.strip = strip;
D.status = 0;
DumpHeader(&D);
DumpByte(f->sizeupvalues, &D);
DumpFunction(f, NULL, &D);
return D.status;
}

151
deps/lua/lfunc.c vendored Normal file
View File

@@ -0,0 +1,151 @@
/*
** $Id: lfunc.c,v 2.45 2014/11/02 19:19:04 roberto Exp $
** Auxiliary functions to manipulate prototypes and closures
** See Copyright Notice in lua.h
*/
#define lfunc_c
#define LUA_CORE
#include "lprefix.h"
#include <stddef.h>
#include "lua.h"
#include "lfunc.h"
#include "lgc.h"
#include "lmem.h"
#include "lobject.h"
#include "lstate.h"
CClosure *luaF_newCclosure (lua_State *L, int n) {
GCObject *o = luaC_newobj(L, LUA_TCCL, sizeCclosure(n));
CClosure *c = gco2ccl(o);
c->nupvalues = cast_byte(n);
return c;
}
LClosure *luaF_newLclosure (lua_State *L, int n) {
GCObject *o = luaC_newobj(L, LUA_TLCL, sizeLclosure(n));
LClosure *c = gco2lcl(o);
c->p = NULL;
c->nupvalues = cast_byte(n);
while (n--) c->upvals[n] = NULL;
return c;
}
/*
** fill a closure with new closed upvalues
*/
void luaF_initupvals (lua_State *L, LClosure *cl) {
int i;
for (i = 0; i < cl->nupvalues; i++) {
UpVal *uv = luaM_new(L, UpVal);
uv->refcount = 1;
uv->v = &uv->u.value; /* make it closed */
setnilvalue(uv->v);
cl->upvals[i] = uv;
}
}
UpVal *luaF_findupval (lua_State *L, StkId level) {
UpVal **pp = &L->openupval;
UpVal *p;
UpVal *uv;
lua_assert(isintwups(L) || L->openupval == NULL);
while (*pp != NULL && (p = *pp)->v >= level) {
lua_assert(upisopen(p));
if (p->v == level) /* found a corresponding upvalue? */
return p; /* return it */
pp = &p->u.open.next;
}
/* not found: create a new upvalue */
uv = luaM_new(L, UpVal);
uv->refcount = 0;
uv->u.open.next = *pp; /* link it to list of open upvalues */
uv->u.open.touched = 1;
*pp = uv;
uv->v = level; /* current value lives in the stack */
if (!isintwups(L)) { /* thread not in list of threads with upvalues? */
L->twups = G(L)->twups; /* link it to the list */
G(L)->twups = L;
}
return uv;
}
void luaF_close (lua_State *L, StkId level) {
UpVal *uv;
while (L->openupval != NULL && (uv = L->openupval)->v >= level) {
lua_assert(upisopen(uv));
L->openupval = uv->u.open.next; /* remove from 'open' list */
if (uv->refcount == 0) /* no references? */
luaM_free(L, uv); /* free upvalue */
else {
setobj(L, &uv->u.value, uv->v); /* move value to upvalue slot */
uv->v = &uv->u.value; /* now current value lives here */
luaC_upvalbarrier(L, uv);
}
}
}
Proto *luaF_newproto (lua_State *L) {
GCObject *o = luaC_newobj(L, LUA_TPROTO, sizeof(Proto));
Proto *f = gco2p(o);
f->k = NULL;
f->sizek = 0;
f->p = NULL;
f->sizep = 0;
f->code = NULL;
f->cache = NULL;
f->sizecode = 0;
f->lineinfo = NULL;
f->sizelineinfo = 0;
f->upvalues = NULL;
f->sizeupvalues = 0;
f->numparams = 0;
f->is_vararg = 0;
f->maxstacksize = 0;
f->locvars = NULL;
f->sizelocvars = 0;
f->linedefined = 0;
f->lastlinedefined = 0;
f->source = NULL;
return f;
}
void luaF_freeproto (lua_State *L, Proto *f) {
luaM_freearray(L, f->code, f->sizecode);
luaM_freearray(L, f->p, f->sizep);
luaM_freearray(L, f->k, f->sizek);
luaM_freearray(L, f->lineinfo, f->sizelineinfo);
luaM_freearray(L, f->locvars, f->sizelocvars);
luaM_freearray(L, f->upvalues, f->sizeupvalues);
luaM_free(L, f);
}
/*
** Look for n-th local variable at line 'line' in function 'func'.
** Returns NULL if not found.
*/
const char *luaF_getlocalname (const Proto *f, int local_number, int pc) {
int i;
for (i = 0; i<f->sizelocvars && f->locvars[i].startpc <= pc; i++) {
if (pc < f->locvars[i].endpc) { /* is variable active? */
local_number--;
if (local_number == 0)
return getstr(f->locvars[i].varname);
}
}
return NULL; /* not found */
}

61
deps/lua/lfunc.h vendored Normal file
View File

@@ -0,0 +1,61 @@
/*
** $Id: lfunc.h,v 2.15 2015/01/13 15:49:11 roberto Exp $
** Auxiliary functions to manipulate prototypes and closures
** See Copyright Notice in lua.h
*/
#ifndef lfunc_h
#define lfunc_h
#include "lobject.h"
#define sizeCclosure(n) (cast(int, sizeof(CClosure)) + \
cast(int, sizeof(TValue)*((n)-1)))
#define sizeLclosure(n) (cast(int, sizeof(LClosure)) + \
cast(int, sizeof(TValue *)*((n)-1)))
/* test whether thread is in 'twups' list */
#define isintwups(L) (L->twups != L)
/*
** maximum number of upvalues in a closure (both C and Lua). (Value
** must fit in a VM register.)
*/
#define MAXUPVAL 255
/*
** Upvalues for Lua closures
*/
struct UpVal {
TValue *v; /* points to stack or to its own value */
lu_mem refcount; /* reference counter */
union {
struct { /* (when open) */
UpVal *next; /* linked list */
int touched; /* mark to avoid cycles with dead threads */
} open;
TValue value; /* the value (when closed) */
} u;
};
#define upisopen(up) ((up)->v != &(up)->u.value)
LUAI_FUNC Proto *luaF_newproto (lua_State *L);
LUAI_FUNC CClosure *luaF_newCclosure (lua_State *L, int nelems);
LUAI_FUNC LClosure *luaF_newLclosure (lua_State *L, int nelems);
LUAI_FUNC void luaF_initupvals (lua_State *L, LClosure *cl);
LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level);
LUAI_FUNC void luaF_close (lua_State *L, StkId level);
LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f);
LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number,
int pc);
#endif

1176
deps/lua/lgc.c vendored Normal file

File diff suppressed because it is too large Load Diff

147
deps/lua/lgc.h vendored Normal file
View File

@@ -0,0 +1,147 @@
/*
** $Id: lgc.h,v 2.91 2015/12/21 13:02:14 roberto Exp $
** Garbage Collector
** See Copyright Notice in lua.h
*/
#ifndef lgc_h
#define lgc_h
#include "lobject.h"
#include "lstate.h"
/*
** Collectable objects may have one of three colors: white, which
** means the object is not marked; gray, which means the
** object is marked, but its references may be not marked; and
** black, which means that the object and all its references are marked.
** The main invariant of the garbage collector, while marking objects,
** is that a black object can never point to a white one. Moreover,
** any gray object must be in a "gray list" (gray, grayagain, weak,
** allweak, ephemeron) so that it can be visited again before finishing
** the collection cycle. These lists have no meaning when the invariant
** is not being enforced (e.g., sweep phase).
*/
/* how much to allocate before next GC step */
#if !defined(GCSTEPSIZE)
/* ~100 small strings */
#define GCSTEPSIZE (cast_int(100 * sizeof(TString)))
#endif
/*
** Possible states of the Garbage Collector
*/
#define GCSpropagate 0
#define GCSatomic 1
#define GCSswpallgc 2
#define GCSswpfinobj 3
#define GCSswptobefnz 4
#define GCSswpend 5
#define GCScallfin 6
#define GCSpause 7
#define issweepphase(g) \
(GCSswpallgc <= (g)->gcstate && (g)->gcstate <= GCSswpend)
/*
** macro to tell when main invariant (white objects cannot point to black
** ones) must be kept. During a collection, the sweep
** phase may break the invariant, as objects turned white may point to
** still-black objects. The invariant is restored when sweep ends and
** all objects are white again.
*/
#define keepinvariant(g) ((g)->gcstate <= GCSatomic)
/*
** some useful bit tricks
*/
#define resetbits(x,m) ((x) &= cast(lu_byte, ~(m)))
#define setbits(x,m) ((x) |= (m))
#define testbits(x,m) ((x) & (m))
#define bitmask(b) (1<<(b))
#define bit2mask(b1,b2) (bitmask(b1) | bitmask(b2))
#define l_setbit(x,b) setbits(x, bitmask(b))
#define resetbit(x,b) resetbits(x, bitmask(b))
#define testbit(x,b) testbits(x, bitmask(b))
/* Layout for bit use in 'marked' field: */
#define WHITE0BIT 0 /* object is white (type 0) */
#define WHITE1BIT 1 /* object is white (type 1) */
#define BLACKBIT 2 /* object is black */
#define FINALIZEDBIT 3 /* object has been marked for finalization */
/* bit 7 is currently used by tests (luaL_checkmemory) */
#define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT)
#define iswhite(x) testbits((x)->marked, WHITEBITS)
#define isblack(x) testbit((x)->marked, BLACKBIT)
#define isgray(x) /* neither white nor black */ \
(!testbits((x)->marked, WHITEBITS | bitmask(BLACKBIT)))
#define tofinalize(x) testbit((x)->marked, FINALIZEDBIT)
#define otherwhite(g) ((g)->currentwhite ^ WHITEBITS)
#define isdeadm(ow,m) (!(((m) ^ WHITEBITS) & (ow)))
#define isdead(g,v) isdeadm(otherwhite(g), (v)->marked)
#define changewhite(x) ((x)->marked ^= WHITEBITS)
#define gray2black(x) l_setbit((x)->marked, BLACKBIT)
#define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS)
/*
** Does one step of collection when debt becomes positive. 'pre'/'pos'
** allows some adjustments to be done only when needed. macro
** 'condchangemem' is used only for heavy tests (forcing a full
** GC cycle on every opportunity)
*/
#define luaC_condGC(L,pre,pos) \
{ if (G(L)->GCdebt > 0) { pre; luaC_step(L); pos;}; \
condchangemem(L,pre,pos); }
/* more often than not, 'pre'/'pos' are empty */
#define luaC_checkGC(L) luaC_condGC(L,(void)0,(void)0)
#define luaC_barrier(L,p,v) ( \
(iscollectable(v) && isblack(p) && iswhite(gcvalue(v))) ? \
luaC_barrier_(L,obj2gco(p),gcvalue(v)) : cast_void(0))
#define luaC_barrierback(L,p,v) ( \
(iscollectable(v) && isblack(p) && iswhite(gcvalue(v))) ? \
luaC_barrierback_(L,p) : cast_void(0))
#define luaC_objbarrier(L,p,o) ( \
(isblack(p) && iswhite(o)) ? \
luaC_barrier_(L,obj2gco(p),obj2gco(o)) : cast_void(0))
#define luaC_upvalbarrier(L,uv) ( \
(iscollectable((uv)->v) && !upisopen(uv)) ? \
luaC_upvalbarrier_(L,uv) : cast_void(0))
LUAI_FUNC void luaC_fix (lua_State *L, GCObject *o);
LUAI_FUNC void luaC_freeallobjects (lua_State *L);
LUAI_FUNC void luaC_step (lua_State *L);
LUAI_FUNC void luaC_runtilstate (lua_State *L, int statesmask);
LUAI_FUNC void luaC_fullgc (lua_State *L, int isemergency);
LUAI_FUNC GCObject *luaC_newobj (lua_State *L, int tt, size_t sz);
LUAI_FUNC void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v);
LUAI_FUNC void luaC_barrierback_ (lua_State *L, Table *o);
LUAI_FUNC void luaC_upvalbarrier_ (lua_State *L, UpVal *uv);
LUAI_FUNC void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt);
LUAI_FUNC void luaC_upvdeccount (lua_State *L, UpVal *uv);
#endif

68
deps/lua/linit.c vendored Normal file
View File

@@ -0,0 +1,68 @@
/*
** $Id: linit.c,v 1.38 2015/01/05 13:48:33 roberto Exp $
** Initialization of libraries for lua.c and other clients
** See Copyright Notice in lua.h
*/
#define linit_c
#define LUA_LIB
/*
** If you embed Lua in your program and need to open the standard
** libraries, call luaL_openlibs in your program. If you need a
** different set of libraries, copy this file to your project and edit
** it to suit your needs.
**
** You can also *preload* libraries, so that a later 'require' can
** open the library, which is already linked to the application.
** For that, do the following code:
**
** luaL_getsubtable(L, LUA_REGISTRYINDEX, "_PRELOAD");
** lua_pushcfunction(L, luaopen_modname);
** lua_setfield(L, -2, modname);
** lua_pop(L, 1); // remove _PRELOAD table
*/
#include "lprefix.h"
#include <stddef.h>
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
/*
** these libs are loaded by lua.c and are readily available to any Lua
** program
*/
static const luaL_Reg loadedlibs[] = {
{"_G", luaopen_base},
{LUA_LOADLIBNAME, luaopen_package},
{LUA_COLIBNAME, luaopen_coroutine},
{LUA_TABLIBNAME, luaopen_table},
{LUA_IOLIBNAME, luaopen_io},
{LUA_OSLIBNAME, luaopen_os},
{LUA_STRLIBNAME, luaopen_string},
{LUA_MATHLIBNAME, luaopen_math},
{LUA_UTF8LIBNAME, luaopen_utf8},
{LUA_DBLIBNAME, luaopen_debug},
#if defined(LUA_COMPAT_BITLIB)
{LUA_BITLIBNAME, luaopen_bit32},
#endif
{NULL, NULL}
};
LUALIB_API void luaL_openlibs (lua_State *L) {
const luaL_Reg *lib;
/* "require" functions from 'loadedlibs' and set results to global table */
for (lib = loadedlibs; lib->func; lib++) {
luaL_requiref(L, lib->name, lib->func, 1);
lua_pop(L, 1); /* remove lib */
}
}

768
deps/lua/liolib.c vendored Normal file
View File

@@ -0,0 +1,768 @@
/*
** $Id: liolib.c,v 2.149 2016/05/02 14:03:19 roberto Exp $
** Standard I/O (and system) library
** See Copyright Notice in lua.h
*/
#define liolib_c
#define LUA_LIB
#include "lprefix.h"
#include <ctype.h>
#include <errno.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
/*
** Change this macro to accept other modes for 'fopen' besides
** the standard ones.
*/
#if !defined(l_checkmode)
/* accepted extensions to 'mode' in 'fopen' */
#if !defined(L_MODEEXT)
#define L_MODEEXT "b"
#endif
/* Check whether 'mode' matches '[rwa]%+?[L_MODEEXT]*' */
#define l_checkmode(mode) \
(*mode != '\0' && strchr("rwa", *(mode++)) != NULL && \
(*mode != '+' || (++mode, 1)) && /* skip if char is '+' */ \
(strspn(mode, L_MODEEXT) == strlen(mode)))
#endif
/*
** {======================================================
** l_popen spawns a new process connected to the current
** one through the file streams.
** =======================================================
*/
#if !defined(l_popen) /* { */
#if defined(LUA_USE_POSIX) /* { */
#define l_popen(L,c,m) (fflush(NULL), popen(c,m))
#define l_pclose(L,file) (pclose(file))
#elif defined(LUA_USE_WINDOWS) /* }{ */
#define l_popen(L,c,m) (_popen(c,m))
#define l_pclose(L,file) (_pclose(file))
#else /* }{ */
/* ISO C definitions */
#define l_popen(L,c,m) \
((void)((void)c, m), \
luaL_error(L, "'popen' not supported"), \
(FILE*)0)
#define l_pclose(L,file) ((void)L, (void)file, -1)
#endif /* } */
#endif /* } */
/* }====================================================== */
#if !defined(l_getc) /* { */
#if defined(LUA_USE_POSIX)
#define l_getc(f) getc_unlocked(f)
#define l_lockfile(f) flockfile(f)
#define l_unlockfile(f) funlockfile(f)
#else
#define l_getc(f) getc(f)
#define l_lockfile(f) ((void)0)
#define l_unlockfile(f) ((void)0)
#endif
#endif /* } */
/*
** {======================================================
** l_fseek: configuration for longer offsets
** =======================================================
*/
#if !defined(l_fseek) /* { */
#if defined(LUA_USE_POSIX) /* { */
#include <sys/types.h>
#define l_fseek(f,o,w) fseeko(f,o,w)
#define l_ftell(f) ftello(f)
#define l_seeknum off_t
#elif defined(LUA_USE_WINDOWS) && !defined(_CRTIMP_TYPEINFO) \
&& defined(_MSC_VER) && (_MSC_VER >= 1400) /* }{ */
/* Windows (but not DDK) and Visual C++ 2005 or higher */
#define l_fseek(f,o,w) _fseeki64(f,o,w)
#define l_ftell(f) _ftelli64(f)
#define l_seeknum __int64
#else /* }{ */
/* ISO C definitions */
#define l_fseek(f,o,w) fseek(f,o,w)
#define l_ftell(f) ftell(f)
#define l_seeknum long
#endif /* } */
#endif /* } */
/* }====================================================== */
#define IO_PREFIX "_IO_"
#define IOPREF_LEN (sizeof(IO_PREFIX)/sizeof(char) - 1)
#define IO_INPUT (IO_PREFIX "input")
#define IO_OUTPUT (IO_PREFIX "output")
typedef luaL_Stream LStream;
#define tolstream(L) ((LStream *)luaL_checkudata(L, 1, LUA_FILEHANDLE))
#define isclosed(p) ((p)->closef == NULL)
static int io_type (lua_State *L) {
LStream *p;
luaL_checkany(L, 1);
p = (LStream *)luaL_testudata(L, 1, LUA_FILEHANDLE);
if (p == NULL)
lua_pushnil(L); /* not a file */
else if (isclosed(p))
lua_pushliteral(L, "closed file");
else
lua_pushliteral(L, "file");
return 1;
}
static int f_tostring (lua_State *L) {
LStream *p = tolstream(L);
if (isclosed(p))
lua_pushliteral(L, "file (closed)");
else
lua_pushfstring(L, "file (%p)", p->f);
return 1;
}
static FILE *tofile (lua_State *L) {
LStream *p = tolstream(L);
if (isclosed(p))
luaL_error(L, "attempt to use a closed file");
lua_assert(p->f);
return p->f;
}
/*
** When creating file handles, always creates a 'closed' file handle
** before opening the actual file; so, if there is a memory error, the
** handle is in a consistent state.
*/
static LStream *newprefile (lua_State *L) {
LStream *p = (LStream *)lua_newuserdata(L, sizeof(LStream));
p->closef = NULL; /* mark file handle as 'closed' */
luaL_setmetatable(L, LUA_FILEHANDLE);
return p;
}
/*
** Calls the 'close' function from a file handle. The 'volatile' avoids
** a bug in some versions of the Clang compiler (e.g., clang 3.0 for
** 32 bits).
*/
static int aux_close (lua_State *L) {
LStream *p = tolstream(L);
volatile lua_CFunction cf = p->closef;
p->closef = NULL; /* mark stream as closed */
return (*cf)(L); /* close it */
}
static int io_close (lua_State *L) {
if (lua_isnone(L, 1)) /* no argument? */
lua_getfield(L, LUA_REGISTRYINDEX, IO_OUTPUT); /* use standard output */
tofile(L); /* make sure argument is an open stream */
return aux_close(L);
}
static int f_gc (lua_State *L) {
LStream *p = tolstream(L);
if (!isclosed(p) && p->f != NULL)
aux_close(L); /* ignore closed and incompletely open files */
return 0;
}
/*
** function to close regular files
*/
static int io_fclose (lua_State *L) {
LStream *p = tolstream(L);
int res = fclose(p->f);
return luaL_fileresult(L, (res == 0), NULL);
}
static LStream *newfile (lua_State *L) {
LStream *p = newprefile(L);
p->f = NULL;
p->closef = &io_fclose;
return p;
}
static void opencheck (lua_State *L, const char *fname, const char *mode) {
LStream *p = newfile(L);
p->f = fopen(fname, mode);
if (p->f == NULL)
luaL_error(L, "cannot open file '%s' (%s)", fname, strerror(errno));
}
static int io_open (lua_State *L) {
const char *filename = luaL_checkstring(L, 1);
const char *mode = luaL_optstring(L, 2, "r");
LStream *p = newfile(L);
const char *md = mode; /* to traverse/check mode */
luaL_argcheck(L, l_checkmode(md), 2, "invalid mode");
p->f = fopen(filename, mode);
return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1;
}
/*
** function to close 'popen' files
*/
static int io_pclose (lua_State *L) {
LStream *p = tolstream(L);
return luaL_execresult(L, l_pclose(L, p->f));
}
static int io_popen (lua_State *L) {
const char *filename = luaL_checkstring(L, 1);
const char *mode = luaL_optstring(L, 2, "r");
LStream *p = newprefile(L);
p->f = l_popen(L, filename, mode);
p->closef = &io_pclose;
return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1;
}
static int io_tmpfile (lua_State *L) {
LStream *p = newfile(L);
p->f = tmpfile();
return (p->f == NULL) ? luaL_fileresult(L, 0, NULL) : 1;
}
static FILE *getiofile (lua_State *L, const char *findex) {
LStream *p;
lua_getfield(L, LUA_REGISTRYINDEX, findex);
p = (LStream *)lua_touserdata(L, -1);
if (isclosed(p))
luaL_error(L, "standard %s file is closed", findex + IOPREF_LEN);
return p->f;
}
static int g_iofile (lua_State *L, const char *f, const char *mode) {
if (!lua_isnoneornil(L, 1)) {
const char *filename = lua_tostring(L, 1);
if (filename)
opencheck(L, filename, mode);
else {
tofile(L); /* check that it's a valid file handle */
lua_pushvalue(L, 1);
}
lua_setfield(L, LUA_REGISTRYINDEX, f);
}
/* return current value */
lua_getfield(L, LUA_REGISTRYINDEX, f);
return 1;
}
static int io_input (lua_State *L) {
return g_iofile(L, IO_INPUT, "r");
}
static int io_output (lua_State *L) {
return g_iofile(L, IO_OUTPUT, "w");
}
static int io_readline (lua_State *L);
/*
** maximum number of arguments to 'f:lines'/'io.lines' (it + 3 must fit
** in the limit for upvalues of a closure)
*/
#define MAXARGLINE 250
static void aux_lines (lua_State *L, int toclose) {
int n = lua_gettop(L) - 1; /* number of arguments to read */
luaL_argcheck(L, n <= MAXARGLINE, MAXARGLINE + 2, "too many arguments");
lua_pushinteger(L, n); /* number of arguments to read */
lua_pushboolean(L, toclose); /* close/not close file when finished */
lua_rotate(L, 2, 2); /* move 'n' and 'toclose' to their positions */
lua_pushcclosure(L, io_readline, 3 + n);
}
static int f_lines (lua_State *L) {
tofile(L); /* check that it's a valid file handle */
aux_lines(L, 0);
return 1;
}
static int io_lines (lua_State *L) {
int toclose;
if (lua_isnone(L, 1)) lua_pushnil(L); /* at least one argument */
if (lua_isnil(L, 1)) { /* no file name? */
lua_getfield(L, LUA_REGISTRYINDEX, IO_INPUT); /* get default input */
lua_replace(L, 1); /* put it at index 1 */
tofile(L); /* check that it's a valid file handle */
toclose = 0; /* do not close it after iteration */
}
else { /* open a new file */
const char *filename = luaL_checkstring(L, 1);
opencheck(L, filename, "r");
lua_replace(L, 1); /* put file at index 1 */
toclose = 1; /* close it after iteration */
}
aux_lines(L, toclose);
return 1;
}
/*
** {======================================================
** READ
** =======================================================
*/
/* maximum length of a numeral */
#if !defined (L_MAXLENNUM)
#define L_MAXLENNUM 200
#endif
/* auxiliary structure used by 'read_number' */
typedef struct {
FILE *f; /* file being read */
int c; /* current character (look ahead) */
int n; /* number of elements in buffer 'buff' */
char buff[L_MAXLENNUM + 1]; /* +1 for ending '\0' */
} RN;
/*
** Add current char to buffer (if not out of space) and read next one
*/
static int nextc (RN *rn) {
if (rn->n >= L_MAXLENNUM) { /* buffer overflow? */
rn->buff[0] = '\0'; /* invalidate result */
return 0; /* fail */
}
else {
rn->buff[rn->n++] = rn->c; /* save current char */
rn->c = l_getc(rn->f); /* read next one */
return 1;
}
}
/*
** Accept current char if it is in 'set' (of size 2)
*/
static int test2 (RN *rn, const char *set) {
if (rn->c == set[0] || rn->c == set[1])
return nextc(rn);
else return 0;
}
/*
** Read a sequence of (hex)digits
*/
static int readdigits (RN *rn, int hex) {
int count = 0;
while ((hex ? isxdigit(rn->c) : isdigit(rn->c)) && nextc(rn))
count++;
return count;
}
/*
** Read a number: first reads a valid prefix of a numeral into a buffer.
** Then it calls 'lua_stringtonumber' to check whether the format is
** correct and to convert it to a Lua number
*/
static int read_number (lua_State *L, FILE *f) {
RN rn;
int count = 0;
int hex = 0;
char decp[2];
rn.f = f; rn.n = 0;
decp[0] = lua_getlocaledecpoint(); /* get decimal point from locale */
decp[1] = '.'; /* always accept a dot */
l_lockfile(rn.f);
do { rn.c = l_getc(rn.f); } while (isspace(rn.c)); /* skip spaces */
test2(&rn, "-+"); /* optional signal */
if (test2(&rn, "00")) {
if (test2(&rn, "xX")) hex = 1; /* numeral is hexadecimal */
else count = 1; /* count initial '0' as a valid digit */
}
count += readdigits(&rn, hex); /* integral part */
if (test2(&rn, decp)) /* decimal point? */
count += readdigits(&rn, hex); /* fractional part */
if (count > 0 && test2(&rn, (hex ? "pP" : "eE"))) { /* exponent mark? */
test2(&rn, "-+"); /* exponent signal */
readdigits(&rn, 0); /* exponent digits */
}
ungetc(rn.c, rn.f); /* unread look-ahead char */
l_unlockfile(rn.f);
rn.buff[rn.n] = '\0'; /* finish string */
if (lua_stringtonumber(L, rn.buff)) /* is this a valid number? */
return 1; /* ok */
else { /* invalid format */
lua_pushnil(L); /* "result" to be removed */
return 0; /* read fails */
}
}
static int test_eof (lua_State *L, FILE *f) {
int c = getc(f);
ungetc(c, f); /* no-op when c == EOF */
lua_pushliteral(L, "");
return (c != EOF);
}
static int read_line (lua_State *L, FILE *f, int chop) {
luaL_Buffer b;
int c = '\0';
luaL_buffinit(L, &b);
while (c != EOF && c != '\n') { /* repeat until end of line */
char *buff = luaL_prepbuffer(&b); /* preallocate buffer */
int i = 0;
l_lockfile(f); /* no memory errors can happen inside the lock */
while (i < LUAL_BUFFERSIZE && (c = l_getc(f)) != EOF && c != '\n')
buff[i++] = c;
l_unlockfile(f);
luaL_addsize(&b, i);
}
if (!chop && c == '\n') /* want a newline and have one? */
luaL_addchar(&b, c); /* add ending newline to result */
luaL_pushresult(&b); /* close buffer */
/* return ok if read something (either a newline or something else) */
return (c == '\n' || lua_rawlen(L, -1) > 0);
}
static void read_all (lua_State *L, FILE *f) {
size_t nr;
luaL_Buffer b;
luaL_buffinit(L, &b);
do { /* read file in chunks of LUAL_BUFFERSIZE bytes */
char *p = luaL_prepbuffer(&b);
nr = fread(p, sizeof(char), LUAL_BUFFERSIZE, f);
luaL_addsize(&b, nr);
} while (nr == LUAL_BUFFERSIZE);
luaL_pushresult(&b); /* close buffer */
}
static int read_chars (lua_State *L, FILE *f, size_t n) {
size_t nr; /* number of chars actually read */
char *p;
luaL_Buffer b;
luaL_buffinit(L, &b);
p = luaL_prepbuffsize(&b, n); /* prepare buffer to read whole block */
nr = fread(p, sizeof(char), n, f); /* try to read 'n' chars */
luaL_addsize(&b, nr);
luaL_pushresult(&b); /* close buffer */
return (nr > 0); /* true iff read something */
}
static int g_read (lua_State *L, FILE *f, int first) {
int nargs = lua_gettop(L) - 1;
int success;
int n;
clearerr(f);
if (nargs == 0) { /* no arguments? */
success = read_line(L, f, 1);
n = first+1; /* to return 1 result */
}
else { /* ensure stack space for all results and for auxlib's buffer */
luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments");
success = 1;
for (n = first; nargs-- && success; n++) {
if (lua_type(L, n) == LUA_TNUMBER) {
size_t l = (size_t)luaL_checkinteger(L, n);
success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l);
}
else {
const char *p = luaL_checkstring(L, n);
if (*p == '*') p++; /* skip optional '*' (for compatibility) */
switch (*p) {
case 'n': /* number */
success = read_number(L, f);
break;
case 'l': /* line */
success = read_line(L, f, 1);
break;
case 'L': /* line with end-of-line */
success = read_line(L, f, 0);
break;
case 'a': /* file */
read_all(L, f); /* read entire file */
success = 1; /* always success */
break;
default:
return luaL_argerror(L, n, "invalid format");
}
}
}
}
if (ferror(f))
return luaL_fileresult(L, 0, NULL);
if (!success) {
lua_pop(L, 1); /* remove last result */
lua_pushnil(L); /* push nil instead */
}
return n - first;
}
static int io_read (lua_State *L) {
return g_read(L, getiofile(L, IO_INPUT), 1);
}
static int f_read (lua_State *L) {
return g_read(L, tofile(L), 2);
}
static int io_readline (lua_State *L) {
LStream *p = (LStream *)lua_touserdata(L, lua_upvalueindex(1));
int i;
int n = (int)lua_tointeger(L, lua_upvalueindex(2));
if (isclosed(p)) /* file is already closed? */
return luaL_error(L, "file is already closed");
lua_settop(L , 1);
luaL_checkstack(L, n, "too many arguments");
for (i = 1; i <= n; i++) /* push arguments to 'g_read' */
lua_pushvalue(L, lua_upvalueindex(3 + i));
n = g_read(L, p->f, 2); /* 'n' is number of results */
lua_assert(n > 0); /* should return at least a nil */
if (lua_toboolean(L, -n)) /* read at least one value? */
return n; /* return them */
else { /* first result is nil: EOF or error */
if (n > 1) { /* is there error information? */
/* 2nd result is error message */
return luaL_error(L, "%s", lua_tostring(L, -n + 1));
}
if (lua_toboolean(L, lua_upvalueindex(3))) { /* generator created file? */
lua_settop(L, 0);
lua_pushvalue(L, lua_upvalueindex(1));
aux_close(L); /* close it */
}
return 0;
}
}
/* }====================================================== */
static int g_write (lua_State *L, FILE *f, int arg) {
int nargs = lua_gettop(L) - arg;
int status = 1;
for (; nargs--; arg++) {
if (lua_type(L, arg) == LUA_TNUMBER) {
/* optimization: could be done exactly as for strings */
int len = lua_isinteger(L, arg)
? fprintf(f, LUA_INTEGER_FMT, lua_tointeger(L, arg))
: fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg));
status = status && (len > 0);
}
else {
size_t l;
const char *s = luaL_checklstring(L, arg, &l);
status = status && (fwrite(s, sizeof(char), l, f) == l);
}
}
if (status) return 1; /* file handle already on stack top */
else return luaL_fileresult(L, status, NULL);
}
static int io_write (lua_State *L) {
return g_write(L, getiofile(L, IO_OUTPUT), 1);
}
static int f_write (lua_State *L) {
FILE *f = tofile(L);
lua_pushvalue(L, 1); /* push file at the stack top (to be returned) */
return g_write(L, f, 2);
}
static int f_seek (lua_State *L) {
static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END};
static const char *const modenames[] = {"set", "cur", "end", NULL};
FILE *f = tofile(L);
int op = luaL_checkoption(L, 2, "cur", modenames);
lua_Integer p3 = luaL_optinteger(L, 3, 0);
l_seeknum offset = (l_seeknum)p3;
luaL_argcheck(L, (lua_Integer)offset == p3, 3,
"not an integer in proper range");
op = l_fseek(f, offset, mode[op]);
if (op)
return luaL_fileresult(L, 0, NULL); /* error */
else {
lua_pushinteger(L, (lua_Integer)l_ftell(f));
return 1;
}
}
static int f_setvbuf (lua_State *L) {
static const int mode[] = {_IONBF, _IOFBF, _IOLBF};
static const char *const modenames[] = {"no", "full", "line", NULL};
FILE *f = tofile(L);
int op = luaL_checkoption(L, 2, NULL, modenames);
lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE);
int res = setvbuf(f, NULL, mode[op], (size_t)sz);
return luaL_fileresult(L, res == 0, NULL);
}
static int io_flush (lua_State *L) {
return luaL_fileresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL);
}
static int f_flush (lua_State *L) {
return luaL_fileresult(L, fflush(tofile(L)) == 0, NULL);
}
/*
** functions for 'io' library
*/
static const luaL_Reg iolib[] = {
{"close", io_close},
{"flush", io_flush},
{"input", io_input},
{"lines", io_lines},
{"open", io_open},
{"output", io_output},
{"popen", io_popen},
{"read", io_read},
{"tmpfile", io_tmpfile},
{"type", io_type},
{"write", io_write},
{NULL, NULL}
};
/*
** methods for file handles
*/
static const luaL_Reg flib[] = {
{"close", io_close},
{"flush", f_flush},
{"lines", f_lines},
{"read", f_read},
{"seek", f_seek},
{"setvbuf", f_setvbuf},
{"write", f_write},
{"__gc", f_gc},
{"__tostring", f_tostring},
{NULL, NULL}
};
static void createmeta (lua_State *L) {
luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file handles */
lua_pushvalue(L, -1); /* push metatable */
lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */
luaL_setfuncs(L, flib, 0); /* add file methods to new metatable */
lua_pop(L, 1); /* pop new metatable */
}
/*
** function to (not) close the standard files stdin, stdout, and stderr
*/
static int io_noclose (lua_State *L) {
LStream *p = tolstream(L);
p->closef = &io_noclose; /* keep file opened */
lua_pushnil(L);
lua_pushliteral(L, "cannot close standard file");
return 2;
}
static void createstdfile (lua_State *L, FILE *f, const char *k,
const char *fname) {
LStream *p = newprefile(L);
p->f = f;
p->closef = &io_noclose;
if (k != NULL) {
lua_pushvalue(L, -1);
lua_setfield(L, LUA_REGISTRYINDEX, k); /* add file to registry */
}
lua_setfield(L, -2, fname); /* add file to module */
}
LUAMOD_API int luaopen_io (lua_State *L) {
luaL_newlib(L, iolib); /* new module */
createmeta(L);
/* create (and set) default files */
createstdfile(L, stdin, IO_INPUT, "stdin");
createstdfile(L, stdout, IO_OUTPUT, "stdout");
createstdfile(L, stderr, NULL, "stderr");
return 1;
}

565
deps/lua/llex.c vendored Normal file
View File

@@ -0,0 +1,565 @@
/*
** $Id: llex.c,v 2.96 2016/05/02 14:02:12 roberto Exp $
** Lexical Analyzer
** See Copyright Notice in lua.h
*/
#define llex_c
#define LUA_CORE
#include "lprefix.h"
#include <locale.h>
#include <string.h>
#include "lua.h"
#include "lctype.h"
#include "ldebug.h"
#include "ldo.h"
#include "lgc.h"
#include "llex.h"
#include "lobject.h"
#include "lparser.h"
#include "lstate.h"
#include "lstring.h"
#include "ltable.h"
#include "lzio.h"
#define next(ls) (ls->current = zgetc(ls->z))
#define currIsNewline(ls) (ls->current == '\n' || ls->current == '\r')
/* ORDER RESERVED */
static const char *const luaX_tokens [] = {
"and", "break", "do", "else", "elseif",
"end", "false", "for", "function", "goto", "if",
"in", "local", "nil", "not", "or", "repeat",
"return", "then", "true", "until", "while",
"//", "..", "...", "==", ">=", "<=", "~=",
"<<", ">>", "::", "<eof>",
"<number>", "<integer>", "<name>", "<string>"
};
#define save_and_next(ls) (save(ls, ls->current), next(ls))
static l_noret lexerror (LexState *ls, const char *msg, int token);
static void save (LexState *ls, int c) {
Mbuffer *b = ls->buff;
if (luaZ_bufflen(b) + 1 > luaZ_sizebuffer(b)) {
size_t newsize;
if (luaZ_sizebuffer(b) >= MAX_SIZE/2)
lexerror(ls, "lexical element too long", 0);
newsize = luaZ_sizebuffer(b) * 2;
luaZ_resizebuffer(ls->L, b, newsize);
}
b->buffer[luaZ_bufflen(b)++] = cast(char, c);
}
void luaX_init (lua_State *L) {
int i;
TString *e = luaS_newliteral(L, LUA_ENV); /* create env name */
luaC_fix(L, obj2gco(e)); /* never collect this name */
for (i=0; i<NUM_RESERVED; i++) {
TString *ts = luaS_new(L, luaX_tokens[i]);
luaC_fix(L, obj2gco(ts)); /* reserved words are never collected */
ts->extra = cast_byte(i+1); /* reserved word */
}
}
const char *luaX_token2str (LexState *ls, int token) {
if (token < FIRST_RESERVED) { /* single-byte symbols? */
lua_assert(token == cast_uchar(token));
return luaO_pushfstring(ls->L, "'%c'", token);
}
else {
const char *s = luaX_tokens[token - FIRST_RESERVED];
if (token < TK_EOS) /* fixed format (symbols and reserved words)? */
return luaO_pushfstring(ls->L, "'%s'", s);
else /* names, strings, and numerals */
return s;
}
}
static const char *txtToken (LexState *ls, int token) {
switch (token) {
case TK_NAME: case TK_STRING:
case TK_FLT: case TK_INT:
save(ls, '\0');
return luaO_pushfstring(ls->L, "'%s'", luaZ_buffer(ls->buff));
default:
return luaX_token2str(ls, token);
}
}
static l_noret lexerror (LexState *ls, const char *msg, int token) {
msg = luaG_addinfo(ls->L, msg, ls->source, ls->linenumber);
if (token)
luaO_pushfstring(ls->L, "%s near %s", msg, txtToken(ls, token));
luaD_throw(ls->L, LUA_ERRSYNTAX);
}
l_noret luaX_syntaxerror (LexState *ls, const char *msg) {
lexerror(ls, msg, ls->t.token);
}
/*
** creates a new string and anchors it in scanner's table so that
** it will not be collected until the end of the compilation
** (by that time it should be anchored somewhere)
*/
TString *luaX_newstring (LexState *ls, const char *str, size_t l) {
lua_State *L = ls->L;
TValue *o; /* entry for 'str' */
TString *ts = luaS_newlstr(L, str, l); /* create new string */
setsvalue2s(L, L->top++, ts); /* temporarily anchor it in stack */
o = luaH_set(L, ls->h, L->top - 1);
if (ttisnil(o)) { /* not in use yet? */
/* boolean value does not need GC barrier;
table has no metatable, so it does not need to invalidate cache */
setbvalue(o, 1); /* t[string] = true */
luaC_checkGC(L);
}
else { /* string already present */
ts = tsvalue(keyfromval(o)); /* re-use value previously stored */
}
L->top--; /* remove string from stack */
return ts;
}
/*
** increment line number and skips newline sequence (any of
** \n, \r, \n\r, or \r\n)
*/
static void inclinenumber (LexState *ls) {
int old = ls->current;
lua_assert(currIsNewline(ls));
next(ls); /* skip '\n' or '\r' */
if (currIsNewline(ls) && ls->current != old)
next(ls); /* skip '\n\r' or '\r\n' */
if (++ls->linenumber >= MAX_INT)
lexerror(ls, "chunk has too many lines", 0);
}
void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source,
int firstchar) {
ls->t.token = 0;
ls->L = L;
ls->current = firstchar;
ls->lookahead.token = TK_EOS; /* no look-ahead token */
ls->z = z;
ls->fs = NULL;
ls->linenumber = 1;
ls->lastline = 1;
ls->source = source;
ls->envn = luaS_newliteral(L, LUA_ENV); /* get env name */
luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER); /* initialize buffer */
}
/*
** =======================================================
** LEXICAL ANALYZER
** =======================================================
*/
static int check_next1 (LexState *ls, int c) {
if (ls->current == c) {
next(ls);
return 1;
}
else return 0;
}
/*
** Check whether current char is in set 'set' (with two chars) and
** saves it
*/
static int check_next2 (LexState *ls, const char *set) {
lua_assert(set[2] == '\0');
if (ls->current == set[0] || ls->current == set[1]) {
save_and_next(ls);
return 1;
}
else return 0;
}
/* LUA_NUMBER */
/*
** this function is quite liberal in what it accepts, as 'luaO_str2num'
** will reject ill-formed numerals.
*/
static int read_numeral (LexState *ls, SemInfo *seminfo) {
TValue obj;
const char *expo = "Ee";
int first = ls->current;
lua_assert(lisdigit(ls->current));
save_and_next(ls);
if (first == '0' && check_next2(ls, "xX")) /* hexadecimal? */
expo = "Pp";
for (;;) {
if (check_next2(ls, expo)) /* exponent part? */
check_next2(ls, "-+"); /* optional exponent sign */
if (lisxdigit(ls->current))
save_and_next(ls);
else if (ls->current == '.')
save_and_next(ls);
else break;
}
save(ls, '\0');
if (luaO_str2num(luaZ_buffer(ls->buff), &obj) == 0) /* format error? */
lexerror(ls, "malformed number", TK_FLT);
if (ttisinteger(&obj)) {
seminfo->i = ivalue(&obj);
return TK_INT;
}
else {
lua_assert(ttisfloat(&obj));
seminfo->r = fltvalue(&obj);
return TK_FLT;
}
}
/*
** skip a sequence '[=*[' or ']=*]'; if sequence is well formed, return
** its number of '='s; otherwise, return a negative number (-1 iff there
** are no '='s after initial bracket)
*/
static int skip_sep (LexState *ls) {
int count = 0;
int s = ls->current;
lua_assert(s == '[' || s == ']');
save_and_next(ls);
while (ls->current == '=') {
save_and_next(ls);
count++;
}
return (ls->current == s) ? count : (-count) - 1;
}
static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) {
int line = ls->linenumber; /* initial line (for error message) */
save_and_next(ls); /* skip 2nd '[' */
if (currIsNewline(ls)) /* string starts with a newline? */
inclinenumber(ls); /* skip it */
for (;;) {
switch (ls->current) {
case EOZ: { /* error */
const char *what = (seminfo ? "string" : "comment");
const char *msg = luaO_pushfstring(ls->L,
"unfinished long %s (starting at line %d)", what, line);
lexerror(ls, msg, TK_EOS);
break; /* to avoid warnings */
}
case ']': {
if (skip_sep(ls) == sep) {
save_and_next(ls); /* skip 2nd ']' */
goto endloop;
}
break;
}
case '\n': case '\r': {
save(ls, '\n');
inclinenumber(ls);
if (!seminfo) luaZ_resetbuffer(ls->buff); /* avoid wasting space */
break;
}
default: {
if (seminfo) save_and_next(ls);
else next(ls);
}
}
} endloop:
if (seminfo)
seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + (2 + sep),
luaZ_bufflen(ls->buff) - 2*(2 + sep));
}
static void esccheck (LexState *ls, int c, const char *msg) {
if (!c) {
if (ls->current != EOZ)
save_and_next(ls); /* add current to buffer for error message */
lexerror(ls, msg, TK_STRING);
}
}
static int gethexa (LexState *ls) {
save_and_next(ls);
esccheck (ls, lisxdigit(ls->current), "hexadecimal digit expected");
return luaO_hexavalue(ls->current);
}
static int readhexaesc (LexState *ls) {
int r = gethexa(ls);
r = (r << 4) + gethexa(ls);
luaZ_buffremove(ls->buff, 2); /* remove saved chars from buffer */
return r;
}
static unsigned long readutf8esc (LexState *ls) {
unsigned long r;
int i = 4; /* chars to be removed: '\', 'u', '{', and first digit */
save_and_next(ls); /* skip 'u' */
esccheck(ls, ls->current == '{', "missing '{'");
r = gethexa(ls); /* must have at least one digit */
while ((save_and_next(ls), lisxdigit(ls->current))) {
i++;
r = (r << 4) + luaO_hexavalue(ls->current);
esccheck(ls, r <= 0x10FFFF, "UTF-8 value too large");
}
esccheck(ls, ls->current == '}', "missing '}'");
next(ls); /* skip '}' */
luaZ_buffremove(ls->buff, i); /* remove saved chars from buffer */
return r;
}
static void utf8esc (LexState *ls) {
char buff[UTF8BUFFSZ];
int n = luaO_utf8esc(buff, readutf8esc(ls));
for (; n > 0; n--) /* add 'buff' to string */
save(ls, buff[UTF8BUFFSZ - n]);
}
static int readdecesc (LexState *ls) {
int i;
int r = 0; /* result accumulator */
for (i = 0; i < 3 && lisdigit(ls->current); i++) { /* read up to 3 digits */
r = 10*r + ls->current - '0';
save_and_next(ls);
}
esccheck(ls, r <= UCHAR_MAX, "decimal escape too large");
luaZ_buffremove(ls->buff, i); /* remove read digits from buffer */
return r;
}
static void read_string (LexState *ls, int del, SemInfo *seminfo) {
save_and_next(ls); /* keep delimiter (for error messages) */
while (ls->current != del) {
switch (ls->current) {
case EOZ:
lexerror(ls, "unfinished string", TK_EOS);
break; /* to avoid warnings */
case '\n':
case '\r':
lexerror(ls, "unfinished string", TK_STRING);
break; /* to avoid warnings */
case '\\': { /* escape sequences */
int c; /* final character to be saved */
save_and_next(ls); /* keep '\\' for error messages */
switch (ls->current) {
case 'a': c = '\a'; goto read_save;
case 'b': c = '\b'; goto read_save;
case 'f': c = '\f'; goto read_save;
case 'n': c = '\n'; goto read_save;
case 'r': c = '\r'; goto read_save;
case 't': c = '\t'; goto read_save;
case 'v': c = '\v'; goto read_save;
case 'x': c = readhexaesc(ls); goto read_save;
case 'u': utf8esc(ls); goto no_save;
case '\n': case '\r':
inclinenumber(ls); c = '\n'; goto only_save;
case '\\': case '\"': case '\'':
c = ls->current; goto read_save;
case EOZ: goto no_save; /* will raise an error next loop */
case 'z': { /* zap following span of spaces */
luaZ_buffremove(ls->buff, 1); /* remove '\\' */
next(ls); /* skip the 'z' */
while (lisspace(ls->current)) {
if (currIsNewline(ls)) inclinenumber(ls);
else next(ls);
}
goto no_save;
}
default: {
esccheck(ls, lisdigit(ls->current), "invalid escape sequence");
c = readdecesc(ls); /* digital escape '\ddd' */
goto only_save;
}
}
read_save:
next(ls);
/* go through */
only_save:
luaZ_buffremove(ls->buff, 1); /* remove '\\' */
save(ls, c);
/* go through */
no_save: break;
}
default:
save_and_next(ls);
}
}
save_and_next(ls); /* skip delimiter */
seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + 1,
luaZ_bufflen(ls->buff) - 2);
}
static int llex (LexState *ls, SemInfo *seminfo) {
luaZ_resetbuffer(ls->buff);
for (;;) {
switch (ls->current) {
case '\n': case '\r': { /* line breaks */
inclinenumber(ls);
break;
}
case ' ': case '\f': case '\t': case '\v': { /* spaces */
next(ls);
break;
}
case '-': { /* '-' or '--' (comment) */
next(ls);
if (ls->current != '-') return '-';
/* else is a comment */
next(ls);
if (ls->current == '[') { /* long comment? */
int sep = skip_sep(ls);
luaZ_resetbuffer(ls->buff); /* 'skip_sep' may dirty the buffer */
if (sep >= 0) {
read_long_string(ls, NULL, sep); /* skip long comment */
luaZ_resetbuffer(ls->buff); /* previous call may dirty the buff. */
break;
}
}
/* else short comment */
while (!currIsNewline(ls) && ls->current != EOZ)
next(ls); /* skip until end of line (or end of file) */
break;
}
case '[': { /* long string or simply '[' */
int sep = skip_sep(ls);
if (sep >= 0) {
read_long_string(ls, seminfo, sep);
return TK_STRING;
}
else if (sep != -1) /* '[=...' missing second bracket */
lexerror(ls, "invalid long string delimiter", TK_STRING);
return '[';
}
case '=': {
next(ls);
if (check_next1(ls, '=')) return TK_EQ;
else return '=';
}
case '<': {
next(ls);
if (check_next1(ls, '=')) return TK_LE;
else if (check_next1(ls, '<')) return TK_SHL;
else return '<';
}
case '>': {
next(ls);
if (check_next1(ls, '=')) return TK_GE;
else if (check_next1(ls, '>')) return TK_SHR;
else return '>';
}
case '/': {
next(ls);
if (check_next1(ls, '/')) return TK_IDIV;
else return '/';
}
case '~': {
next(ls);
if (check_next1(ls, '=')) return TK_NE;
else return '~';
}
case ':': {
next(ls);
if (check_next1(ls, ':')) return TK_DBCOLON;
else return ':';
}
case '"': case '\'': { /* short literal strings */
read_string(ls, ls->current, seminfo);
return TK_STRING;
}
case '.': { /* '.', '..', '...', or number */
save_and_next(ls);
if (check_next1(ls, '.')) {
if (check_next1(ls, '.'))
return TK_DOTS; /* '...' */
else return TK_CONCAT; /* '..' */
}
else if (!lisdigit(ls->current)) return '.';
else return read_numeral(ls, seminfo);
}
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9': {
return read_numeral(ls, seminfo);
}
case EOZ: {
return TK_EOS;
}
default: {
if (lislalpha(ls->current)) { /* identifier or reserved word? */
TString *ts;
do {
save_and_next(ls);
} while (lislalnum(ls->current));
ts = luaX_newstring(ls, luaZ_buffer(ls->buff),
luaZ_bufflen(ls->buff));
seminfo->ts = ts;
if (isreserved(ts)) /* reserved word? */
return ts->extra - 1 + FIRST_RESERVED;
else {
return TK_NAME;
}
}
else { /* single-char tokens (+ - / ...) */
int c = ls->current;
next(ls);
return c;
}
}
}
}
}
void luaX_next (LexState *ls) {
ls->lastline = ls->linenumber;
if (ls->lookahead.token != TK_EOS) { /* is there a look-ahead token? */
ls->t = ls->lookahead; /* use this one */
ls->lookahead.token = TK_EOS; /* and discharge it */
}
else
ls->t.token = llex(ls, &ls->t.seminfo); /* read next token */
}
int luaX_lookahead (LexState *ls) {
lua_assert(ls->lookahead.token == TK_EOS);
ls->lookahead.token = llex(ls, &ls->lookahead.seminfo);
return ls->lookahead.token;
}

85
deps/lua/llex.h vendored Normal file
View File

@@ -0,0 +1,85 @@
/*
** $Id: llex.h,v 1.79 2016/05/02 14:02:12 roberto Exp $
** Lexical Analyzer
** See Copyright Notice in lua.h
*/
#ifndef llex_h
#define llex_h
#include "lobject.h"
#include "lzio.h"
#define FIRST_RESERVED 257
#if !defined(LUA_ENV)
#define LUA_ENV "_ENV"
#endif
/*
* WARNING: if you change the order of this enumeration,
* grep "ORDER RESERVED"
*/
enum RESERVED {
/* terminal symbols denoted by reserved words */
TK_AND = FIRST_RESERVED, TK_BREAK,
TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION,
TK_GOTO, TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT,
TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE,
/* other terminal symbols */
TK_IDIV, TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE,
TK_SHL, TK_SHR,
TK_DBCOLON, TK_EOS,
TK_FLT, TK_INT, TK_NAME, TK_STRING
};
/* number of reserved words */
#define NUM_RESERVED (cast(int, TK_WHILE-FIRST_RESERVED+1))
typedef union {
lua_Number r;
lua_Integer i;
TString *ts;
} SemInfo; /* semantics information */
typedef struct Token {
int token;
SemInfo seminfo;
} Token;
/* state of the lexer plus state of the parser when shared by all
functions */
typedef struct LexState {
int current; /* current character (charint) */
int linenumber; /* input line counter */
int lastline; /* line of last token 'consumed' */
Token t; /* current token */
Token lookahead; /* look ahead token */
struct FuncState *fs; /* current function (parser) */
struct lua_State *L;
ZIO *z; /* input stream */
Mbuffer *buff; /* buffer for tokens */
Table *h; /* to avoid collection/reuse strings */
struct Dyndata *dyd; /* dynamic structures used by the parser */
TString *source; /* current source name */
TString *envn; /* environment variable name */
} LexState;
LUAI_FUNC void luaX_init (lua_State *L);
LUAI_FUNC void luaX_setinput (lua_State *L, LexState *ls, ZIO *z,
TString *source, int firstchar);
LUAI_FUNC TString *luaX_newstring (LexState *ls, const char *str, size_t l);
LUAI_FUNC void luaX_next (LexState *ls);
LUAI_FUNC int luaX_lookahead (LexState *ls);
LUAI_FUNC l_noret luaX_syntaxerror (LexState *ls, const char *s);
LUAI_FUNC const char *luaX_token2str (LexState *ls, int token);
#endif

323
deps/lua/llimits.h vendored Normal file
View File

@@ -0,0 +1,323 @@
/*
** $Id: llimits.h,v 1.141 2015/11/19 19:16:22 roberto Exp $
** Limits, basic types, and some other 'installation-dependent' definitions
** See Copyright Notice in lua.h
*/
#ifndef llimits_h
#define llimits_h
#include <limits.h>
#include <stddef.h>
#include "lua.h"
/*
** 'lu_mem' and 'l_mem' are unsigned/signed integers big enough to count
** the total memory used by Lua (in bytes). Usually, 'size_t' and
** 'ptrdiff_t' should work, but we use 'long' for 16-bit machines.
*/
#if defined(LUAI_MEM) /* { external definitions? */
typedef LUAI_UMEM lu_mem;
typedef LUAI_MEM l_mem;
#elif LUAI_BITSINT >= 32 /* }{ */
typedef size_t lu_mem;
typedef ptrdiff_t l_mem;
#else /* 16-bit ints */ /* }{ */
typedef unsigned long lu_mem;
typedef long l_mem;
#endif /* } */
/* chars used as small naturals (so that 'char' is reserved for characters) */
typedef unsigned char lu_byte;
/* maximum value for size_t */
#define MAX_SIZET ((size_t)(~(size_t)0))
/* maximum size visible for Lua (must be representable in a lua_Integer */
#define MAX_SIZE (sizeof(size_t) < sizeof(lua_Integer) ? MAX_SIZET \
: (size_t)(LUA_MAXINTEGER))
#define MAX_LUMEM ((lu_mem)(~(lu_mem)0))
#define MAX_LMEM ((l_mem)(MAX_LUMEM >> 1))
#define MAX_INT INT_MAX /* maximum value of an int */
/*
** conversion of pointer to unsigned integer:
** this is for hashing only; there is no problem if the integer
** cannot hold the whole pointer value
*/
#define point2uint(p) ((unsigned int)((size_t)(p) & UINT_MAX))
/* type to ensure maximum alignment */
#if defined(LUAI_USER_ALIGNMENT_T)
typedef LUAI_USER_ALIGNMENT_T L_Umaxalign;
#else
typedef union {
lua_Number n;
double u;
void *s;
lua_Integer i;
long l;
} L_Umaxalign;
#endif
/* types of 'usual argument conversions' for lua_Number and lua_Integer */
typedef LUAI_UACNUMBER l_uacNumber;
typedef LUAI_UACINT l_uacInt;
/* internal assertions for in-house debugging */
#if defined(lua_assert)
#define check_exp(c,e) (lua_assert(c), (e))
/* to avoid problems with conditions too long */
#define lua_longassert(c) ((c) ? (void)0 : lua_assert(0))
#else
#define lua_assert(c) ((void)0)
#define check_exp(c,e) (e)
#define lua_longassert(c) ((void)0)
#endif
/*
** assertion for checking API calls
*/
#if !defined(luai_apicheck)
#define luai_apicheck(l,e) lua_assert(e)
#endif
#define api_check(l,e,msg) luai_apicheck(l,(e) && msg)
/* macro to avoid warnings about unused variables */
#if !defined(UNUSED)
#define UNUSED(x) ((void)(x))
#endif
/* type casts (a macro highlights casts in the code) */
#define cast(t, exp) ((t)(exp))
#define cast_void(i) cast(void, (i))
#define cast_byte(i) cast(lu_byte, (i))
#define cast_num(i) cast(lua_Number, (i))
#define cast_int(i) cast(int, (i))
#define cast_uchar(i) cast(unsigned char, (i))
/* cast a signed lua_Integer to lua_Unsigned */
#if !defined(l_castS2U)
#define l_castS2U(i) ((lua_Unsigned)(i))
#endif
/*
** cast a lua_Unsigned to a signed lua_Integer; this cast is
** not strict ISO C, but two-complement architectures should
** work fine.
*/
#if !defined(l_castU2S)
#define l_castU2S(i) ((lua_Integer)(i))
#endif
/*
** non-return type
*/
#if defined(__GNUC__)
#define l_noret void __attribute__((noreturn))
#elif defined(_MSC_VER) && _MSC_VER >= 1200
#define l_noret void __declspec(noreturn)
#else
#define l_noret void
#endif
/*
** maximum depth for nested C calls and syntactical nested non-terminals
** in a program. (Value must fit in an unsigned short int.)
*/
#if !defined(LUAI_MAXCCALLS)
#define LUAI_MAXCCALLS 200
#endif
/*
** type for virtual-machine instructions;
** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h)
*/
#if LUAI_BITSINT >= 32
typedef unsigned int Instruction;
#else
typedef unsigned long Instruction;
#endif
/*
** Maximum length for short strings, that is, strings that are
** internalized. (Cannot be smaller than reserved words or tags for
** metamethods, as these strings must be internalized;
** #("function") = 8, #("__newindex") = 10.)
*/
#if !defined(LUAI_MAXSHORTLEN)
#define LUAI_MAXSHORTLEN 40
#endif
/*
** Initial size for the string table (must be power of 2).
** The Lua core alone registers ~50 strings (reserved words +
** metaevent keys + a few others). Libraries would typically add
** a few dozens more.
*/
#if !defined(MINSTRTABSIZE)
#define MINSTRTABSIZE 128
#endif
/*
** Size of cache for strings in the API. 'N' is the number of
** sets (better be a prime) and "M" is the size of each set (M == 1
** makes a direct cache.)
*/
#if !defined(STRCACHE_N)
#define STRCACHE_N 53
#define STRCACHE_M 2
#endif
/* minimum size for string buffer */
#if !defined(LUA_MINBUFFER)
#define LUA_MINBUFFER 32
#endif
/*
** macros that are executed whenever program enters the Lua core
** ('lua_lock') and leaves the core ('lua_unlock')
*/
#if !defined(lua_lock)
#define lua_lock(L) ((void) 0)
#define lua_unlock(L) ((void) 0)
#endif
/*
** macro executed during Lua functions at points where the
** function can yield.
*/
#if !defined(luai_threadyield)
#define luai_threadyield(L) {lua_unlock(L); lua_lock(L);}
#endif
/*
** these macros allow user-specific actions on threads when you defined
** LUAI_EXTRASPACE and need to do something extra when a thread is
** created/deleted/resumed/yielded.
*/
#if !defined(luai_userstateopen)
#define luai_userstateopen(L) ((void)L)
#endif
#if !defined(luai_userstateclose)
#define luai_userstateclose(L) ((void)L)
#endif
#if !defined(luai_userstatethread)
#define luai_userstatethread(L,L1) ((void)L)
#endif
#if !defined(luai_userstatefree)
#define luai_userstatefree(L,L1) ((void)L)
#endif
#if !defined(luai_userstateresume)
#define luai_userstateresume(L,n) ((void)L)
#endif
#if !defined(luai_userstateyield)
#define luai_userstateyield(L,n) ((void)L)
#endif
/*
** The luai_num* macros define the primitive operations over numbers.
*/
/* floor division (defined as 'floor(a/b)') */
#if !defined(luai_numidiv)
#define luai_numidiv(L,a,b) ((void)L, l_floor(luai_numdiv(L,a,b)))
#endif
/* float division */
#if !defined(luai_numdiv)
#define luai_numdiv(L,a,b) ((a)/(b))
#endif
/*
** modulo: defined as 'a - floor(a/b)*b'; this definition gives NaN when
** 'b' is huge, but the result should be 'a'. 'fmod' gives the result of
** 'a - trunc(a/b)*b', and therefore must be corrected when 'trunc(a/b)
** ~= floor(a/b)'. That happens when the division has a non-integer
** negative result, which is equivalent to the test below.
*/
#if !defined(luai_nummod)
#define luai_nummod(L,a,b,m) \
{ (m) = l_mathop(fmod)(a,b); if ((m)*(b) < 0) (m) += (b); }
#endif
/* exponentiation */
#if !defined(luai_numpow)
#define luai_numpow(L,a,b) ((void)L, l_mathop(pow)(a,b))
#endif
/* the others are quite standard operations */
#if !defined(luai_numadd)
#define luai_numadd(L,a,b) ((a)+(b))
#define luai_numsub(L,a,b) ((a)-(b))
#define luai_nummul(L,a,b) ((a)*(b))
#define luai_numunm(L,a) (-(a))
#define luai_numeq(a,b) ((a)==(b))
#define luai_numlt(a,b) ((a)<(b))
#define luai_numle(a,b) ((a)<=(b))
#define luai_numisnan(a) (!luai_numeq((a), (a)))
#endif
/*
** macro to control inclusion of some hard tests on stack reallocation
*/
#if !defined(HARDSTACKTESTS)
#define condmovestack(L,pre,pos) ((void)0)
#else
/* realloc stack keeping its size */
#define condmovestack(L,pre,pos) \
{ int sz_ = (L)->stacksize; pre; luaD_reallocstack((L), sz_); pos; }
#endif
#if !defined(HARDMEMTESTS)
#define condchangemem(L,pre,pos) ((void)0)
#else
#define condchangemem(L,pre,pos) \
{ if (G(L)->gcrunning) { pre; luaC_fullgc(L, 0); pos; } }
#endif
#endif

407
deps/lua/lmathlib.c vendored Normal file
View File

@@ -0,0 +1,407 @@
/*
** $Id: lmathlib.c,v 1.117 2015/10/02 15:39:23 roberto Exp $
** Standard mathematical library
** See Copyright Notice in lua.h
*/
#define lmathlib_c
#define LUA_LIB
#include "lprefix.h"
#include <stdlib.h>
#include <math.h>
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
#undef PI
#define PI (l_mathop(3.141592653589793238462643383279502884))
#if !defined(l_rand) /* { */
#if defined(LUA_USE_POSIX)
#define l_rand() random()
#define l_srand(x) srandom(x)
#define L_RANDMAX 2147483647 /* (2^31 - 1), following POSIX */
#else
#define l_rand() rand()
#define l_srand(x) srand(x)
#define L_RANDMAX RAND_MAX
#endif
#endif /* } */
static int math_abs (lua_State *L) {
if (lua_isinteger(L, 1)) {
lua_Integer n = lua_tointeger(L, 1);
if (n < 0) n = (lua_Integer)(0u - (lua_Unsigned)n);
lua_pushinteger(L, n);
}
else
lua_pushnumber(L, l_mathop(fabs)(luaL_checknumber(L, 1)));
return 1;
}
static int math_sin (lua_State *L) {
lua_pushnumber(L, l_mathop(sin)(luaL_checknumber(L, 1)));
return 1;
}
static int math_cos (lua_State *L) {
lua_pushnumber(L, l_mathop(cos)(luaL_checknumber(L, 1)));
return 1;
}
static int math_tan (lua_State *L) {
lua_pushnumber(L, l_mathop(tan)(luaL_checknumber(L, 1)));
return 1;
}
static int math_asin (lua_State *L) {
lua_pushnumber(L, l_mathop(asin)(luaL_checknumber(L, 1)));
return 1;
}
static int math_acos (lua_State *L) {
lua_pushnumber(L, l_mathop(acos)(luaL_checknumber(L, 1)));
return 1;
}
static int math_atan (lua_State *L) {
lua_Number y = luaL_checknumber(L, 1);
lua_Number x = luaL_optnumber(L, 2, 1);
lua_pushnumber(L, l_mathop(atan2)(y, x));
return 1;
}
static int math_toint (lua_State *L) {
int valid;
lua_Integer n = lua_tointegerx(L, 1, &valid);
if (valid)
lua_pushinteger(L, n);
else {
luaL_checkany(L, 1);
lua_pushnil(L); /* value is not convertible to integer */
}
return 1;
}
static void pushnumint (lua_State *L, lua_Number d) {
lua_Integer n;
if (lua_numbertointeger(d, &n)) /* does 'd' fit in an integer? */
lua_pushinteger(L, n); /* result is integer */
else
lua_pushnumber(L, d); /* result is float */
}
static int math_floor (lua_State *L) {
if (lua_isinteger(L, 1))
lua_settop(L, 1); /* integer is its own floor */
else {
lua_Number d = l_mathop(floor)(luaL_checknumber(L, 1));
pushnumint(L, d);
}
return 1;
}
static int math_ceil (lua_State *L) {
if (lua_isinteger(L, 1))
lua_settop(L, 1); /* integer is its own ceil */
else {
lua_Number d = l_mathop(ceil)(luaL_checknumber(L, 1));
pushnumint(L, d);
}
return 1;
}
static int math_fmod (lua_State *L) {
if (lua_isinteger(L, 1) && lua_isinteger(L, 2)) {
lua_Integer d = lua_tointeger(L, 2);
if ((lua_Unsigned)d + 1u <= 1u) { /* special cases: -1 or 0 */
luaL_argcheck(L, d != 0, 2, "zero");
lua_pushinteger(L, 0); /* avoid overflow with 0x80000... / -1 */
}
else
lua_pushinteger(L, lua_tointeger(L, 1) % d);
}
else
lua_pushnumber(L, l_mathop(fmod)(luaL_checknumber(L, 1),
luaL_checknumber(L, 2)));
return 1;
}
/*
** next function does not use 'modf', avoiding problems with 'double*'
** (which is not compatible with 'float*') when lua_Number is not
** 'double'.
*/
static int math_modf (lua_State *L) {
if (lua_isinteger(L ,1)) {
lua_settop(L, 1); /* number is its own integer part */
lua_pushnumber(L, 0); /* no fractional part */
}
else {
lua_Number n = luaL_checknumber(L, 1);
/* integer part (rounds toward zero) */
lua_Number ip = (n < 0) ? l_mathop(ceil)(n) : l_mathop(floor)(n);
pushnumint(L, ip);
/* fractional part (test needed for inf/-inf) */
lua_pushnumber(L, (n == ip) ? l_mathop(0.0) : (n - ip));
}
return 2;
}
static int math_sqrt (lua_State *L) {
lua_pushnumber(L, l_mathop(sqrt)(luaL_checknumber(L, 1)));
return 1;
}
static int math_ult (lua_State *L) {
lua_Integer a = luaL_checkinteger(L, 1);
lua_Integer b = luaL_checkinteger(L, 2);
lua_pushboolean(L, (lua_Unsigned)a < (lua_Unsigned)b);
return 1;
}
static int math_log (lua_State *L) {
lua_Number x = luaL_checknumber(L, 1);
lua_Number res;
if (lua_isnoneornil(L, 2))
res = l_mathop(log)(x);
else {
lua_Number base = luaL_checknumber(L, 2);
#if !defined(LUA_USE_C89)
if (base == 2.0) res = l_mathop(log2)(x); else
#endif
if (base == 10.0) res = l_mathop(log10)(x);
else res = l_mathop(log)(x)/l_mathop(log)(base);
}
lua_pushnumber(L, res);
return 1;
}
static int math_exp (lua_State *L) {
lua_pushnumber(L, l_mathop(exp)(luaL_checknumber(L, 1)));
return 1;
}
static int math_deg (lua_State *L) {
lua_pushnumber(L, luaL_checknumber(L, 1) * (l_mathop(180.0) / PI));
return 1;
}
static int math_rad (lua_State *L) {
lua_pushnumber(L, luaL_checknumber(L, 1) * (PI / l_mathop(180.0)));
return 1;
}
static int math_min (lua_State *L) {
int n = lua_gettop(L); /* number of arguments */
int imin = 1; /* index of current minimum value */
int i;
luaL_argcheck(L, n >= 1, 1, "value expected");
for (i = 2; i <= n; i++) {
if (lua_compare(L, i, imin, LUA_OPLT))
imin = i;
}
lua_pushvalue(L, imin);
return 1;
}
static int math_max (lua_State *L) {
int n = lua_gettop(L); /* number of arguments */
int imax = 1; /* index of current maximum value */
int i;
luaL_argcheck(L, n >= 1, 1, "value expected");
for (i = 2; i <= n; i++) {
if (lua_compare(L, imax, i, LUA_OPLT))
imax = i;
}
lua_pushvalue(L, imax);
return 1;
}
/*
** This function uses 'double' (instead of 'lua_Number') to ensure that
** all bits from 'l_rand' can be represented, and that 'RANDMAX + 1.0'
** will keep full precision (ensuring that 'r' is always less than 1.0.)
*/
static int math_random (lua_State *L) {
lua_Integer low, up;
double r = (double)l_rand() * (1.0 / ((double)L_RANDMAX + 1.0));
switch (lua_gettop(L)) { /* check number of arguments */
case 0: { /* no arguments */
lua_pushnumber(L, (lua_Number)r); /* Number between 0 and 1 */
return 1;
}
case 1: { /* only upper limit */
low = 1;
up = luaL_checkinteger(L, 1);
break;
}
case 2: { /* lower and upper limits */
low = luaL_checkinteger(L, 1);
up = luaL_checkinteger(L, 2);
break;
}
default: return luaL_error(L, "wrong number of arguments");
}
/* random integer in the interval [low, up] */
luaL_argcheck(L, low <= up, 1, "interval is empty");
luaL_argcheck(L, low >= 0 || up <= LUA_MAXINTEGER + low, 1,
"interval too large");
r *= (double)(up - low) + 1.0;
lua_pushinteger(L, (lua_Integer)r + low);
return 1;
}
static int math_randomseed (lua_State *L) {
l_srand((unsigned int)(lua_Integer)luaL_checknumber(L, 1));
(void)l_rand(); /* discard first value to avoid undesirable correlations */
return 0;
}
static int math_type (lua_State *L) {
if (lua_type(L, 1) == LUA_TNUMBER) {
if (lua_isinteger(L, 1))
lua_pushliteral(L, "integer");
else
lua_pushliteral(L, "float");
}
else {
luaL_checkany(L, 1);
lua_pushnil(L);
}
return 1;
}
/*
** {==================================================================
** Deprecated functions (for compatibility only)
** ===================================================================
*/
#if defined(LUA_COMPAT_MATHLIB)
static int math_cosh (lua_State *L) {
lua_pushnumber(L, l_mathop(cosh)(luaL_checknumber(L, 1)));
return 1;
}
static int math_sinh (lua_State *L) {
lua_pushnumber(L, l_mathop(sinh)(luaL_checknumber(L, 1)));
return 1;
}
static int math_tanh (lua_State *L) {
lua_pushnumber(L, l_mathop(tanh)(luaL_checknumber(L, 1)));
return 1;
}
static int math_pow (lua_State *L) {
lua_Number x = luaL_checknumber(L, 1);
lua_Number y = luaL_checknumber(L, 2);
lua_pushnumber(L, l_mathop(pow)(x, y));
return 1;
}
static int math_frexp (lua_State *L) {
int e;
lua_pushnumber(L, l_mathop(frexp)(luaL_checknumber(L, 1), &e));
lua_pushinteger(L, e);
return 2;
}
static int math_ldexp (lua_State *L) {
lua_Number x = luaL_checknumber(L, 1);
int ep = (int)luaL_checkinteger(L, 2);
lua_pushnumber(L, l_mathop(ldexp)(x, ep));
return 1;
}
static int math_log10 (lua_State *L) {
lua_pushnumber(L, l_mathop(log10)(luaL_checknumber(L, 1)));
return 1;
}
#endif
/* }================================================================== */
static const luaL_Reg mathlib[] = {
{"abs", math_abs},
{"acos", math_acos},
{"asin", math_asin},
{"atan", math_atan},
{"ceil", math_ceil},
{"cos", math_cos},
{"deg", math_deg},
{"exp", math_exp},
{"tointeger", math_toint},
{"floor", math_floor},
{"fmod", math_fmod},
{"ult", math_ult},
{"log", math_log},
{"max", math_max},
{"min", math_min},
{"modf", math_modf},
{"rad", math_rad},
{"random", math_random},
{"randomseed", math_randomseed},
{"sin", math_sin},
{"sqrt", math_sqrt},
{"tan", math_tan},
{"type", math_type},
#if defined(LUA_COMPAT_MATHLIB)
{"atan2", math_atan},
{"cosh", math_cosh},
{"sinh", math_sinh},
{"tanh", math_tanh},
{"pow", math_pow},
{"frexp", math_frexp},
{"ldexp", math_ldexp},
{"log10", math_log10},
#endif
/* placeholders */
{"pi", NULL},
{"huge", NULL},
{"maxinteger", NULL},
{"mininteger", NULL},
{NULL, NULL}
};
/*
** Open math library
*/
LUAMOD_API int luaopen_math (lua_State *L) {
luaL_newlib(L, mathlib);
lua_pushnumber(L, PI);
lua_setfield(L, -2, "pi");
lua_pushnumber(L, (lua_Number)HUGE_VAL);
lua_setfield(L, -2, "huge");
lua_pushinteger(L, LUA_MAXINTEGER);
lua_setfield(L, -2, "maxinteger");
lua_pushinteger(L, LUA_MININTEGER);
lua_setfield(L, -2, "mininteger");
return 1;
}

100
deps/lua/lmem.c vendored Normal file
View File

@@ -0,0 +1,100 @@
/*
** $Id: lmem.c,v 1.91 2015/03/06 19:45:54 roberto Exp $
** Interface to Memory Manager
** See Copyright Notice in lua.h
*/
#define lmem_c
#define LUA_CORE
#include "lprefix.h"
#include <stddef.h>
#include "lua.h"
#include "ldebug.h"
#include "ldo.h"
#include "lgc.h"
#include "lmem.h"
#include "lobject.h"
#include "lstate.h"
/*
** About the realloc function:
** void * frealloc (void *ud, void *ptr, size_t osize, size_t nsize);
** ('osize' is the old size, 'nsize' is the new size)
**
** * frealloc(ud, NULL, x, s) creates a new block of size 's' (no
** matter 'x').
**
** * frealloc(ud, p, x, 0) frees the block 'p'
** (in this specific case, frealloc must return NULL);
** particularly, frealloc(ud, NULL, 0, 0) does nothing
** (which is equivalent to free(NULL) in ISO C)
**
** frealloc returns NULL if it cannot create or reallocate the area
** (any reallocation to an equal or smaller size cannot fail!)
*/
#define MINSIZEARRAY 4
void *luaM_growaux_ (lua_State *L, void *block, int *size, size_t size_elems,
int limit, const char *what) {
void *newblock;
int newsize;
if (*size >= limit/2) { /* cannot double it? */
if (*size >= limit) /* cannot grow even a little? */
luaG_runerror(L, "too many %s (limit is %d)", what, limit);
newsize = limit; /* still have at least one free place */
}
else {
newsize = (*size)*2;
if (newsize < MINSIZEARRAY)
newsize = MINSIZEARRAY; /* minimum size */
}
newblock = luaM_reallocv(L, block, *size, newsize, size_elems);
*size = newsize; /* update only when everything else is OK */
return newblock;
}
l_noret luaM_toobig (lua_State *L) {
luaG_runerror(L, "memory allocation error: block too big");
}
/*
** generic allocation routine.
*/
void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) {
void *newblock;
global_State *g = G(L);
size_t realosize = (block) ? osize : 0;
lua_assert((realosize == 0) == (block == NULL));
#if defined(HARDMEMTESTS)
if (nsize > realosize && g->gcrunning)
luaC_fullgc(L, 1); /* force a GC whenever possible */
#endif
newblock = (*g->frealloc)(g->ud, block, osize, nsize);
if (newblock == NULL && nsize > 0) {
lua_assert(nsize > realosize); /* cannot fail when shrinking a block */
if (g->version) { /* is state fully built? */
luaC_fullgc(L, 1); /* try to free some memory... */
newblock = (*g->frealloc)(g->ud, block, osize, nsize); /* try again */
}
if (newblock == NULL)
luaD_throw(L, LUA_ERRMEM);
}
lua_assert((nsize == 0) == (newblock == NULL));
g->GCdebt = (g->GCdebt + nsize) - realosize;
return newblock;
}

69
deps/lua/lmem.h vendored Normal file
View File

@@ -0,0 +1,69 @@
/*
** $Id: lmem.h,v 1.43 2014/12/19 17:26:14 roberto Exp $
** Interface to Memory Manager
** See Copyright Notice in lua.h
*/
#ifndef lmem_h
#define lmem_h
#include <stddef.h>
#include "llimits.h"
#include "lua.h"
/*
** This macro reallocs a vector 'b' from 'on' to 'n' elements, where
** each element has size 'e'. In case of arithmetic overflow of the
** product 'n'*'e', it raises an error (calling 'luaM_toobig'). Because
** 'e' is always constant, it avoids the runtime division MAX_SIZET/(e).
**
** (The macro is somewhat complex to avoid warnings: The 'sizeof'
** comparison avoids a runtime comparison when overflow cannot occur.
** The compiler should be able to optimize the real test by itself, but
** when it does it, it may give a warning about "comparison is always
** false due to limited range of data type"; the +1 tricks the compiler,
** avoiding this warning but also this optimization.)
*/
#define luaM_reallocv(L,b,on,n,e) \
(((sizeof(n) >= sizeof(size_t) && cast(size_t, (n)) + 1 > MAX_SIZET/(e)) \
? luaM_toobig(L) : cast_void(0)) , \
luaM_realloc_(L, (b), (on)*(e), (n)*(e)))
/*
** Arrays of chars do not need any test
*/
#define luaM_reallocvchar(L,b,on,n) \
cast(char *, luaM_realloc_(L, (b), (on)*sizeof(char), (n)*sizeof(char)))
#define luaM_freemem(L, b, s) luaM_realloc_(L, (b), (s), 0)
#define luaM_free(L, b) luaM_realloc_(L, (b), sizeof(*(b)), 0)
#define luaM_freearray(L, b, n) luaM_realloc_(L, (b), (n)*sizeof(*(b)), 0)
#define luaM_malloc(L,s) luaM_realloc_(L, NULL, 0, (s))
#define luaM_new(L,t) cast(t *, luaM_malloc(L, sizeof(t)))
#define luaM_newvector(L,n,t) \
cast(t *, luaM_reallocv(L, NULL, 0, n, sizeof(t)))
#define luaM_newobject(L,tag,s) luaM_realloc_(L, NULL, tag, (s))
#define luaM_growvector(L,v,nelems,size,t,limit,e) \
if ((nelems)+1 > (size)) \
((v)=cast(t *, luaM_growaux_(L,v,&(size),sizeof(t),limit,e)))
#define luaM_reallocvector(L, v,oldn,n,t) \
((v)=cast(t *, luaM_reallocv(L, v, oldn, n, sizeof(t))))
LUAI_FUNC l_noret luaM_toobig (lua_State *L);
/* not to be called directly */
LUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize,
size_t size);
LUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int *size,
size_t size_elem, int limit,
const char *what);
#endif

787
deps/lua/loadlib.c vendored Normal file
View File

@@ -0,0 +1,787 @@
/*
** $Id: loadlib.c,v 1.127 2015/11/23 11:30:45 roberto Exp $
** Dynamic library loader for Lua
** See Copyright Notice in lua.h
**
** This module contains an implementation of loadlib for Unix systems
** that have dlfcn, an implementation for Windows, and a stub for other
** systems.
*/
#define loadlib_c
#define LUA_LIB
#include "lprefix.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
/*
** LUA_PATH_VAR and LUA_CPATH_VAR are the names of the environment
** variables that Lua check to set its paths.
*/
#if !defined(LUA_PATH_VAR)
#define LUA_PATH_VAR "LUA_PATH"
#endif
#if !defined(LUA_CPATH_VAR)
#define LUA_CPATH_VAR "LUA_CPATH"
#endif
#define LUA_PATHSUFFIX "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR
#define LUA_PATHVARVERSION LUA_PATH_VAR LUA_PATHSUFFIX
#define LUA_CPATHVARVERSION LUA_CPATH_VAR LUA_PATHSUFFIX
/*
** LUA_PATH_SEP is the character that separates templates in a path.
** LUA_PATH_MARK is the string that marks the substitution points in a
** template.
** LUA_EXEC_DIR in a Windows path is replaced by the executable's
** directory.
** LUA_IGMARK is a mark to ignore all before it when building the
** luaopen_ function name.
*/
#if !defined (LUA_PATH_SEP)
#define LUA_PATH_SEP ";"
#endif
#if !defined (LUA_PATH_MARK)
#define LUA_PATH_MARK "?"
#endif
#if !defined (LUA_EXEC_DIR)
#define LUA_EXEC_DIR "!"
#endif
#if !defined (LUA_IGMARK)
#define LUA_IGMARK "-"
#endif
/*
** LUA_CSUBSEP is the character that replaces dots in submodule names
** when searching for a C loader.
** LUA_LSUBSEP is the character that replaces dots in submodule names
** when searching for a Lua loader.
*/
#if !defined(LUA_CSUBSEP)
#define LUA_CSUBSEP LUA_DIRSEP
#endif
#if !defined(LUA_LSUBSEP)
#define LUA_LSUBSEP LUA_DIRSEP
#endif
/* prefix for open functions in C libraries */
#define LUA_POF "luaopen_"
/* separator for open functions in C libraries */
#define LUA_OFSEP "_"
/*
** unique key for table in the registry that keeps handles
** for all loaded C libraries
*/
static const int CLIBS = 0;
#define LIB_FAIL "open"
#define setprogdir(L) ((void)0)
/*
** system-dependent functions
*/
/*
** unload library 'lib'
*/
static void lsys_unloadlib (void *lib);
/*
** load C library in file 'path'. If 'seeglb', load with all names in
** the library global.
** Returns the library; in case of error, returns NULL plus an
** error string in the stack.
*/
static void *lsys_load (lua_State *L, const char *path, int seeglb);
/*
** Try to find a function named 'sym' in library 'lib'.
** Returns the function; in case of error, returns NULL plus an
** error string in the stack.
*/
static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym);
#if defined(LUA_USE_DLOPEN) /* { */
/*
** {========================================================================
** This is an implementation of loadlib based on the dlfcn interface.
** The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD,
** NetBSD, AIX 4.2, HPUX 11, and probably most other Unix flavors, at least
** as an emulation layer on top of native functions.
** =========================================================================
*/
#include <dlfcn.h>
/*
** Macro to convert pointer-to-void* to pointer-to-function. This cast
** is undefined according to ISO C, but POSIX assumes that it works.
** (The '__extension__' in gnu compilers is only to avoid warnings.)
*/
#if defined(__GNUC__)
#define cast_func(p) (__extension__ (lua_CFunction)(p))
#else
#define cast_func(p) ((lua_CFunction)(p))
#endif
static void lsys_unloadlib (void *lib) {
dlclose(lib);
}
static void *lsys_load (lua_State *L, const char *path, int seeglb) {
void *lib = dlopen(path, RTLD_NOW | (seeglb ? RTLD_GLOBAL : RTLD_LOCAL));
if (lib == NULL) lua_pushstring(L, dlerror());
return lib;
}
static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym) {
lua_CFunction f = cast_func(dlsym(lib, sym));
if (f == NULL) lua_pushstring(L, dlerror());
return f;
}
/* }====================================================== */
#elif defined(LUA_DL_DLL) /* }{ */
/*
** {======================================================================
** This is an implementation of loadlib for Windows using native functions.
** =======================================================================
*/
#include <windows.h>
#undef setprogdir
/*
** optional flags for LoadLibraryEx
*/
#if !defined(LUA_LLE_FLAGS)
#define LUA_LLE_FLAGS 0
#endif
static void setprogdir (lua_State *L) {
char buff[MAX_PATH + 1];
char *lb;
DWORD nsize = sizeof(buff)/sizeof(char);
DWORD n = GetModuleFileNameA(NULL, buff, nsize);
if (n == 0 || n == nsize || (lb = strrchr(buff, '\\')) == NULL)
luaL_error(L, "unable to get ModuleFileName");
else {
*lb = '\0';
luaL_gsub(L, lua_tostring(L, -1), LUA_EXEC_DIR, buff);
lua_remove(L, -2); /* remove original string */
}
}
static void pusherror (lua_State *L) {
int error = GetLastError();
char buffer[128];
if (FormatMessageA(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
NULL, error, 0, buffer, sizeof(buffer)/sizeof(char), NULL))
lua_pushstring(L, buffer);
else
lua_pushfstring(L, "system error %d\n", error);
}
static void lsys_unloadlib (void *lib) {
FreeLibrary((HMODULE)lib);
}
static void *lsys_load (lua_State *L, const char *path, int seeglb) {
HMODULE lib = LoadLibraryExA(path, NULL, LUA_LLE_FLAGS);
(void)(seeglb); /* not used: symbols are 'global' by default */
if (lib == NULL) pusherror(L);
return lib;
}
static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym) {
lua_CFunction f = (lua_CFunction)GetProcAddress((HMODULE)lib, sym);
if (f == NULL) pusherror(L);
return f;
}
/* }====================================================== */
#else /* }{ */
/*
** {======================================================
** Fallback for other systems
** =======================================================
*/
#undef LIB_FAIL
#define LIB_FAIL "absent"
#define DLMSG "dynamic libraries not enabled; check your Lua installation"
static void lsys_unloadlib (void *lib) {
(void)(lib); /* not used */
}
static void *lsys_load (lua_State *L, const char *path, int seeglb) {
(void)(path); (void)(seeglb); /* not used */
lua_pushliteral(L, DLMSG);
return NULL;
}
static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym) {
(void)(lib); (void)(sym); /* not used */
lua_pushliteral(L, DLMSG);
return NULL;
}
/* }====================================================== */
#endif /* } */
/*
** return registry.CLIBS[path]
*/
static void *checkclib (lua_State *L, const char *path) {
void *plib;
lua_rawgetp(L, LUA_REGISTRYINDEX, &CLIBS);
lua_getfield(L, -1, path);
plib = lua_touserdata(L, -1); /* plib = CLIBS[path] */
lua_pop(L, 2); /* pop CLIBS table and 'plib' */
return plib;
}
/*
** registry.CLIBS[path] = plib -- for queries
** registry.CLIBS[#CLIBS + 1] = plib -- also keep a list of all libraries
*/
static void addtoclib (lua_State *L, const char *path, void *plib) {
lua_rawgetp(L, LUA_REGISTRYINDEX, &CLIBS);
lua_pushlightuserdata(L, plib);
lua_pushvalue(L, -1);
lua_setfield(L, -3, path); /* CLIBS[path] = plib */
lua_rawseti(L, -2, luaL_len(L, -2) + 1); /* CLIBS[#CLIBS + 1] = plib */
lua_pop(L, 1); /* pop CLIBS table */
}
/*
** __gc tag method for CLIBS table: calls 'lsys_unloadlib' for all lib
** handles in list CLIBS
*/
static int gctm (lua_State *L) {
lua_Integer n = luaL_len(L, 1);
for (; n >= 1; n--) { /* for each handle, in reverse order */
lua_rawgeti(L, 1, n); /* get handle CLIBS[n] */
lsys_unloadlib(lua_touserdata(L, -1));
lua_pop(L, 1); /* pop handle */
}
return 0;
}
/* error codes for 'lookforfunc' */
#define ERRLIB 1
#define ERRFUNC 2
/*
** Look for a C function named 'sym' in a dynamically loaded library
** 'path'.
** First, check whether the library is already loaded; if not, try
** to load it.
** Then, if 'sym' is '*', return true (as library has been loaded).
** Otherwise, look for symbol 'sym' in the library and push a
** C function with that symbol.
** Return 0 and 'true' or a function in the stack; in case of
** errors, return an error code and an error message in the stack.
*/
static int lookforfunc (lua_State *L, const char *path, const char *sym) {
void *reg = checkclib(L, path); /* check loaded C libraries */
if (reg == NULL) { /* must load library? */
reg = lsys_load(L, path, *sym == '*'); /* global symbols if 'sym'=='*' */
if (reg == NULL) return ERRLIB; /* unable to load library */
addtoclib(L, path, reg);
}
if (*sym == '*') { /* loading only library (no function)? */
lua_pushboolean(L, 1); /* return 'true' */
return 0; /* no errors */
}
else {
lua_CFunction f = lsys_sym(L, reg, sym);
if (f == NULL)
return ERRFUNC; /* unable to find function */
lua_pushcfunction(L, f); /* else create new function */
return 0; /* no errors */
}
}
static int ll_loadlib (lua_State *L) {
const char *path = luaL_checkstring(L, 1);
const char *init = luaL_checkstring(L, 2);
int stat = lookforfunc(L, path, init);
if (stat == 0) /* no errors? */
return 1; /* return the loaded function */
else { /* error; error message is on stack top */
lua_pushnil(L);
lua_insert(L, -2);
lua_pushstring(L, (stat == ERRLIB) ? LIB_FAIL : "init");
return 3; /* return nil, error message, and where */
}
}
/*
** {======================================================
** 'require' function
** =======================================================
*/
static int readable (const char *filename) {
FILE *f = fopen(filename, "r"); /* try to open file */
if (f == NULL) return 0; /* open failed */
fclose(f);
return 1;
}
static const char *pushnexttemplate (lua_State *L, const char *path) {
const char *l;
while (*path == *LUA_PATH_SEP) path++; /* skip separators */
if (*path == '\0') return NULL; /* no more templates */
l = strchr(path, *LUA_PATH_SEP); /* find next separator */
if (l == NULL) l = path + strlen(path);
lua_pushlstring(L, path, l - path); /* template */
return l;
}
static const char *searchpath (lua_State *L, const char *name,
const char *path,
const char *sep,
const char *dirsep) {
luaL_Buffer msg; /* to build error message */
luaL_buffinit(L, &msg);
if (*sep != '\0') /* non-empty separator? */
name = luaL_gsub(L, name, sep, dirsep); /* replace it by 'dirsep' */
while ((path = pushnexttemplate(L, path)) != NULL) {
const char *filename = luaL_gsub(L, lua_tostring(L, -1),
LUA_PATH_MARK, name);
lua_remove(L, -2); /* remove path template */
if (readable(filename)) /* does file exist and is readable? */
return filename; /* return that file name */
lua_pushfstring(L, "\n\tno file '%s'", filename);
lua_remove(L, -2); /* remove file name */
luaL_addvalue(&msg); /* concatenate error msg. entry */
}
luaL_pushresult(&msg); /* create error message */
return NULL; /* not found */
}
static int ll_searchpath (lua_State *L) {
const char *f = searchpath(L, luaL_checkstring(L, 1),
luaL_checkstring(L, 2),
luaL_optstring(L, 3, "."),
luaL_optstring(L, 4, LUA_DIRSEP));
if (f != NULL) return 1;
else { /* error message is on top of the stack */
lua_pushnil(L);
lua_insert(L, -2);
return 2; /* return nil + error message */
}
}
static const char *findfile (lua_State *L, const char *name,
const char *pname,
const char *dirsep) {
const char *path;
lua_getfield(L, lua_upvalueindex(1), pname);
path = lua_tostring(L, -1);
if (path == NULL)
luaL_error(L, "'package.%s' must be a string", pname);
return searchpath(L, name, path, ".", dirsep);
}
static int checkload (lua_State *L, int stat, const char *filename) {
if (stat) { /* module loaded successfully? */
lua_pushstring(L, filename); /* will be 2nd argument to module */
return 2; /* return open function and file name */
}
else
return luaL_error(L, "error loading module '%s' from file '%s':\n\t%s",
lua_tostring(L, 1), filename, lua_tostring(L, -1));
}
static int searcher_Lua (lua_State *L) {
const char *filename;
const char *name = luaL_checkstring(L, 1);
filename = findfile(L, name, "path", LUA_LSUBSEP);
if (filename == NULL) return 1; /* module not found in this path */
return checkload(L, (luaL_loadfile(L, filename) == LUA_OK), filename);
}
/*
** Try to find a load function for module 'modname' at file 'filename'.
** First, change '.' to '_' in 'modname'; then, if 'modname' has
** the form X-Y (that is, it has an "ignore mark"), build a function
** name "luaopen_X" and look for it. (For compatibility, if that
** fails, it also tries "luaopen_Y".) If there is no ignore mark,
** look for a function named "luaopen_modname".
*/
static int loadfunc (lua_State *L, const char *filename, const char *modname) {
const char *openfunc;
const char *mark;
modname = luaL_gsub(L, modname, ".", LUA_OFSEP);
mark = strchr(modname, *LUA_IGMARK);
if (mark) {
int stat;
openfunc = lua_pushlstring(L, modname, mark - modname);
openfunc = lua_pushfstring(L, LUA_POF"%s", openfunc);
stat = lookforfunc(L, filename, openfunc);
if (stat != ERRFUNC) return stat;
modname = mark + 1; /* else go ahead and try old-style name */
}
openfunc = lua_pushfstring(L, LUA_POF"%s", modname);
return lookforfunc(L, filename, openfunc);
}
static int searcher_C (lua_State *L) {
const char *name = luaL_checkstring(L, 1);
const char *filename = findfile(L, name, "cpath", LUA_CSUBSEP);
if (filename == NULL) return 1; /* module not found in this path */
return checkload(L, (loadfunc(L, filename, name) == 0), filename);
}
static int searcher_Croot (lua_State *L) {
const char *filename;
const char *name = luaL_checkstring(L, 1);
const char *p = strchr(name, '.');
int stat;
if (p == NULL) return 0; /* is root */
lua_pushlstring(L, name, p - name);
filename = findfile(L, lua_tostring(L, -1), "cpath", LUA_CSUBSEP);
if (filename == NULL) return 1; /* root not found */
if ((stat = loadfunc(L, filename, name)) != 0) {
if (stat != ERRFUNC)
return checkload(L, 0, filename); /* real error */
else { /* open function not found */
lua_pushfstring(L, "\n\tno module '%s' in file '%s'", name, filename);
return 1;
}
}
lua_pushstring(L, filename); /* will be 2nd argument to module */
return 2;
}
static int searcher_preload (lua_State *L) {
const char *name = luaL_checkstring(L, 1);
lua_getfield(L, LUA_REGISTRYINDEX, "_PRELOAD");
if (lua_getfield(L, -1, name) == LUA_TNIL) /* not found? */
lua_pushfstring(L, "\n\tno field package.preload['%s']", name);
return 1;
}
static void findloader (lua_State *L, const char *name) {
int i;
luaL_Buffer msg; /* to build error message */
luaL_buffinit(L, &msg);
/* push 'package.searchers' to index 3 in the stack */
if (lua_getfield(L, lua_upvalueindex(1), "searchers") != LUA_TTABLE)
luaL_error(L, "'package.searchers' must be a table");
/* iterate over available searchers to find a loader */
for (i = 1; ; i++) {
if (lua_rawgeti(L, 3, i) == LUA_TNIL) { /* no more searchers? */
lua_pop(L, 1); /* remove nil */
luaL_pushresult(&msg); /* create error message */
luaL_error(L, "module '%s' not found:%s", name, lua_tostring(L, -1));
}
lua_pushstring(L, name);
lua_call(L, 1, 2); /* call it */
if (lua_isfunction(L, -2)) /* did it find a loader? */
return; /* module loader found */
else if (lua_isstring(L, -2)) { /* searcher returned error message? */
lua_pop(L, 1); /* remove extra return */
luaL_addvalue(&msg); /* concatenate error message */
}
else
lua_pop(L, 2); /* remove both returns */
}
}
static int ll_require (lua_State *L) {
const char *name = luaL_checkstring(L, 1);
lua_settop(L, 1); /* _LOADED table will be at index 2 */
lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
lua_getfield(L, 2, name); /* _LOADED[name] */
if (lua_toboolean(L, -1)) /* is it there? */
return 1; /* package is already loaded */
/* else must load package */
lua_pop(L, 1); /* remove 'getfield' result */
findloader(L, name);
lua_pushstring(L, name); /* pass name as argument to module loader */
lua_insert(L, -2); /* name is 1st argument (before search data) */
lua_call(L, 2, 1); /* run loader to load module */
if (!lua_isnil(L, -1)) /* non-nil return? */
lua_setfield(L, 2, name); /* _LOADED[name] = returned value */
if (lua_getfield(L, 2, name) == LUA_TNIL) { /* module set no value? */
lua_pushboolean(L, 1); /* use true as result */
lua_pushvalue(L, -1); /* extra copy to be returned */
lua_setfield(L, 2, name); /* _LOADED[name] = true */
}
return 1;
}
/* }====================================================== */
/*
** {======================================================
** 'module' function
** =======================================================
*/
#if defined(LUA_COMPAT_MODULE)
/*
** changes the environment variable of calling function
*/
static void set_env (lua_State *L) {
lua_Debug ar;
if (lua_getstack(L, 1, &ar) == 0 ||
lua_getinfo(L, "f", &ar) == 0 || /* get calling function */
lua_iscfunction(L, -1))
luaL_error(L, "'module' not called from a Lua function");
lua_pushvalue(L, -2); /* copy new environment table to top */
lua_setupvalue(L, -2, 1);
lua_pop(L, 1); /* remove function */
}
static void dooptions (lua_State *L, int n) {
int i;
for (i = 2; i <= n; i++) {
if (lua_isfunction(L, i)) { /* avoid 'calling' extra info. */
lua_pushvalue(L, i); /* get option (a function) */
lua_pushvalue(L, -2); /* module */
lua_call(L, 1, 0);
}
}
}
static void modinit (lua_State *L, const char *modname) {
const char *dot;
lua_pushvalue(L, -1);
lua_setfield(L, -2, "_M"); /* module._M = module */
lua_pushstring(L, modname);
lua_setfield(L, -2, "_NAME");
dot = strrchr(modname, '.'); /* look for last dot in module name */
if (dot == NULL) dot = modname;
else dot++;
/* set _PACKAGE as package name (full module name minus last part) */
lua_pushlstring(L, modname, dot - modname);
lua_setfield(L, -2, "_PACKAGE");
}
static int ll_module (lua_State *L) {
const char *modname = luaL_checkstring(L, 1);
int lastarg = lua_gettop(L); /* last parameter */
luaL_pushmodule(L, modname, 1); /* get/create module table */
/* check whether table already has a _NAME field */
if (lua_getfield(L, -1, "_NAME") != LUA_TNIL)
lua_pop(L, 1); /* table is an initialized module */
else { /* no; initialize it */
lua_pop(L, 1);
modinit(L, modname);
}
lua_pushvalue(L, -1);
set_env(L);
dooptions(L, lastarg);
return 1;
}
static int ll_seeall (lua_State *L) {
luaL_checktype(L, 1, LUA_TTABLE);
if (!lua_getmetatable(L, 1)) {
lua_createtable(L, 0, 1); /* create new metatable */
lua_pushvalue(L, -1);
lua_setmetatable(L, 1);
}
lua_pushglobaltable(L);
lua_setfield(L, -2, "__index"); /* mt.__index = _G */
return 0;
}
#endif
/* }====================================================== */
/* auxiliary mark (for internal use) */
#define AUXMARK "\1"
/*
** return registry.LUA_NOENV as a boolean
*/
static int noenv (lua_State *L) {
int b;
lua_getfield(L, LUA_REGISTRYINDEX, "LUA_NOENV");
b = lua_toboolean(L, -1);
lua_pop(L, 1); /* remove value */
return b;
}
static void setpath (lua_State *L, const char *fieldname, const char *envname1,
const char *envname2, const char *def) {
const char *path = getenv(envname1);
if (path == NULL) /* no environment variable? */
path = getenv(envname2); /* try alternative name */
if (path == NULL || noenv(L)) /* no environment variable? */
lua_pushstring(L, def); /* use default */
else {
/* replace ";;" by ";AUXMARK;" and then AUXMARK by default path */
path = luaL_gsub(L, path, LUA_PATH_SEP LUA_PATH_SEP,
LUA_PATH_SEP AUXMARK LUA_PATH_SEP);
luaL_gsub(L, path, AUXMARK, def);
lua_remove(L, -2);
}
setprogdir(L);
lua_setfield(L, -2, fieldname);
}
static const luaL_Reg pk_funcs[] = {
{"loadlib", ll_loadlib},
{"searchpath", ll_searchpath},
#if defined(LUA_COMPAT_MODULE)
{"seeall", ll_seeall},
#endif
/* placeholders */
{"preload", NULL},
{"cpath", NULL},
{"path", NULL},
{"searchers", NULL},
{"loaded", NULL},
{NULL, NULL}
};
static const luaL_Reg ll_funcs[] = {
#if defined(LUA_COMPAT_MODULE)
{"module", ll_module},
#endif
{"require", ll_require},
{NULL, NULL}
};
static void createsearcherstable (lua_State *L) {
static const lua_CFunction searchers[] =
{searcher_preload, searcher_Lua, searcher_C, searcher_Croot, NULL};
int i;
/* create 'searchers' table */
lua_createtable(L, sizeof(searchers)/sizeof(searchers[0]) - 1, 0);
/* fill it with predefined searchers */
for (i=0; searchers[i] != NULL; i++) {
lua_pushvalue(L, -2); /* set 'package' as upvalue for all searchers */
lua_pushcclosure(L, searchers[i], 1);
lua_rawseti(L, -2, i+1);
}
#if defined(LUA_COMPAT_LOADERS)
lua_pushvalue(L, -1); /* make a copy of 'searchers' table */
lua_setfield(L, -3, "loaders"); /* put it in field 'loaders' */
#endif
lua_setfield(L, -2, "searchers"); /* put it in field 'searchers' */
}
/*
** create table CLIBS to keep track of loaded C libraries,
** setting a finalizer to close all libraries when closing state.
*/
static void createclibstable (lua_State *L) {
lua_newtable(L); /* create CLIBS table */
lua_createtable(L, 0, 1); /* create metatable for CLIBS */
lua_pushcfunction(L, gctm);
lua_setfield(L, -2, "__gc"); /* set finalizer for CLIBS table */
lua_setmetatable(L, -2);
lua_rawsetp(L, LUA_REGISTRYINDEX, &CLIBS); /* set CLIBS table in registry */
}
LUAMOD_API int luaopen_package (lua_State *L) {
createclibstable(L);
luaL_newlib(L, pk_funcs); /* create 'package' table */
createsearcherstable(L);
/* set field 'path' */
setpath(L, "path", LUA_PATHVARVERSION, LUA_PATH_VAR, LUA_PATH_DEFAULT);
/* set field 'cpath' */
setpath(L, "cpath", LUA_CPATHVARVERSION, LUA_CPATH_VAR, LUA_CPATH_DEFAULT);
/* store config information */
lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATH_SEP "\n" LUA_PATH_MARK "\n"
LUA_EXEC_DIR "\n" LUA_IGMARK "\n");
lua_setfield(L, -2, "config");
/* set field 'loaded' */
luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED");
lua_setfield(L, -2, "loaded");
/* set field 'preload' */
luaL_getsubtable(L, LUA_REGISTRYINDEX, "_PRELOAD");
lua_setfield(L, -2, "preload");
lua_pushglobaltable(L);
lua_pushvalue(L, -2); /* set 'package' as upvalue for next lib */
luaL_setfuncs(L, ll_funcs, 1); /* open lib into global table */
lua_pop(L, 1); /* pop global table */
return 1; /* return 'package' table */
}

521
deps/lua/lobject.c vendored Normal file
View File

@@ -0,0 +1,521 @@
/*
** $Id: lobject.c,v 2.111 2016/05/20 14:07:48 roberto Exp $
** Some generic functions over Lua objects
** See Copyright Notice in lua.h
*/
#define lobject_c
#define LUA_CORE
#include "lprefix.h"
#include <locale.h>
#include <math.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lua.h"
#include "lctype.h"
#include "ldebug.h"
#include "ldo.h"
#include "lmem.h"
#include "lobject.h"
#include "lstate.h"
#include "lstring.h"
#include "lvm.h"
LUAI_DDEF const TValue luaO_nilobject_ = {NILCONSTANT};
/*
** converts an integer to a "floating point byte", represented as
** (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if
** eeeee != 0 and (xxx) otherwise.
*/
int luaO_int2fb (unsigned int x) {
int e = 0; /* exponent */
if (x < 8) return x;
while (x >= (8 << 4)) { /* coarse steps */
x = (x + 0xf) >> 4; /* x = ceil(x / 16) */
e += 4;
}
while (x >= (8 << 1)) { /* fine steps */
x = (x + 1) >> 1; /* x = ceil(x / 2) */
e++;
}
return ((e+1) << 3) | (cast_int(x) - 8);
}
/* converts back */
int luaO_fb2int (int x) {
return (x < 8) ? x : ((x & 7) + 8) << ((x >> 3) - 1);
}
/*
** Computes ceil(log2(x))
*/
int luaO_ceillog2 (unsigned int x) {
static const lu_byte log_2[256] = { /* log_2[i] = ceil(log2(i - 1)) */
0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
};
int l = 0;
x--;
while (x >= 256) { l += 8; x >>= 8; }
return l + log_2[x];
}
static lua_Integer intarith (lua_State *L, int op, lua_Integer v1,
lua_Integer v2) {
switch (op) {
case LUA_OPADD: return intop(+, v1, v2);
case LUA_OPSUB:return intop(-, v1, v2);
case LUA_OPMUL:return intop(*, v1, v2);
case LUA_OPMOD: return luaV_mod(L, v1, v2);
case LUA_OPIDIV: return luaV_div(L, v1, v2);
case LUA_OPBAND: return intop(&, v1, v2);
case LUA_OPBOR: return intop(|, v1, v2);
case LUA_OPBXOR: return intop(^, v1, v2);
case LUA_OPSHL: return luaV_shiftl(v1, v2);
case LUA_OPSHR: return luaV_shiftl(v1, -v2);
case LUA_OPUNM: return intop(-, 0, v1);
case LUA_OPBNOT: return intop(^, ~l_castS2U(0), v1);
default: lua_assert(0); return 0;
}
}
static lua_Number numarith (lua_State *L, int op, lua_Number v1,
lua_Number v2) {
switch (op) {
case LUA_OPADD: return luai_numadd(L, v1, v2);
case LUA_OPSUB: return luai_numsub(L, v1, v2);
case LUA_OPMUL: return luai_nummul(L, v1, v2);
case LUA_OPDIV: return luai_numdiv(L, v1, v2);
case LUA_OPPOW: return luai_numpow(L, v1, v2);
case LUA_OPIDIV: return luai_numidiv(L, v1, v2);
case LUA_OPUNM: return luai_numunm(L, v1);
case LUA_OPMOD: {
lua_Number m;
luai_nummod(L, v1, v2, m);
return m;
}
default: lua_assert(0); return 0;
}
}
void luaO_arith (lua_State *L, int op, const TValue *p1, const TValue *p2,
TValue *res) {
switch (op) {
case LUA_OPBAND: case LUA_OPBOR: case LUA_OPBXOR:
case LUA_OPSHL: case LUA_OPSHR:
case LUA_OPBNOT: { /* operate only on integers */
lua_Integer i1; lua_Integer i2;
if (tointeger(p1, &i1) && tointeger(p2, &i2)) {
setivalue(res, intarith(L, op, i1, i2));
return;
}
else break; /* go to the end */
}
case LUA_OPDIV: case LUA_OPPOW: { /* operate only on floats */
lua_Number n1; lua_Number n2;
if (tonumber(p1, &n1) && tonumber(p2, &n2)) {
setfltvalue(res, numarith(L, op, n1, n2));
return;
}
else break; /* go to the end */
}
default: { /* other operations */
lua_Number n1; lua_Number n2;
if (ttisinteger(p1) && ttisinteger(p2)) {
setivalue(res, intarith(L, op, ivalue(p1), ivalue(p2)));
return;
}
else if (tonumber(p1, &n1) && tonumber(p2, &n2)) {
setfltvalue(res, numarith(L, op, n1, n2));
return;
}
else break; /* go to the end */
}
}
/* could not perform raw operation; try metamethod */
lua_assert(L != NULL); /* should not fail when folding (compile time) */
luaT_trybinTM(L, p1, p2, res, cast(TMS, (op - LUA_OPADD) + TM_ADD));
}
int luaO_hexavalue (int c) {
if (lisdigit(c)) return c - '0';
else return (ltolower(c) - 'a') + 10;
}
static int isneg (const char **s) {
if (**s == '-') { (*s)++; return 1; }
else if (**s == '+') (*s)++;
return 0;
}
/*
** {==================================================================
** Lua's implementation for 'lua_strx2number'
** ===================================================================
*/
#if !defined(lua_strx2number)
/* maximum number of significant digits to read (to avoid overflows
even with single floats) */
#define MAXSIGDIG 30
/*
** convert an hexadecimal numeric string to a number, following
** C99 specification for 'strtod'
*/
static lua_Number lua_strx2number (const char *s, char **endptr) {
int dot = lua_getlocaledecpoint();
lua_Number r = 0.0; /* result (accumulator) */
int sigdig = 0; /* number of significant digits */
int nosigdig = 0; /* number of non-significant digits */
int e = 0; /* exponent correction */
int neg; /* 1 if number is negative */
int hasdot = 0; /* true after seen a dot */
*endptr = cast(char *, s); /* nothing is valid yet */
while (lisspace(cast_uchar(*s))) s++; /* skip initial spaces */
neg = isneg(&s); /* check signal */
if (!(*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X'))) /* check '0x' */
return 0.0; /* invalid format (no '0x') */
for (s += 2; ; s++) { /* skip '0x' and read numeral */
if (*s == dot) {
if (hasdot) break; /* second dot? stop loop */
else hasdot = 1;
}
else if (lisxdigit(cast_uchar(*s))) {
if (sigdig == 0 && *s == '0') /* non-significant digit (zero)? */
nosigdig++;
else if (++sigdig <= MAXSIGDIG) /* can read it without overflow? */
r = (r * cast_num(16.0)) + luaO_hexavalue(*s);
else e++; /* too many digits; ignore, but still count for exponent */
if (hasdot) e--; /* decimal digit? correct exponent */
}
else break; /* neither a dot nor a digit */
}
if (nosigdig + sigdig == 0) /* no digits? */
return 0.0; /* invalid format */
*endptr = cast(char *, s); /* valid up to here */
e *= 4; /* each digit multiplies/divides value by 2^4 */
if (*s == 'p' || *s == 'P') { /* exponent part? */
int exp1 = 0; /* exponent value */
int neg1; /* exponent signal */
s++; /* skip 'p' */
neg1 = isneg(&s); /* signal */
if (!lisdigit(cast_uchar(*s)))
return 0.0; /* invalid; must have at least one digit */
while (lisdigit(cast_uchar(*s))) /* read exponent */
exp1 = exp1 * 10 + *(s++) - '0';
if (neg1) exp1 = -exp1;
e += exp1;
*endptr = cast(char *, s); /* valid up to here */
}
if (neg) r = -r;
return l_mathop(ldexp)(r, e);
}
#endif
/* }====================================================== */
/* maximum length of a numeral */
#if !defined (L_MAXLENNUM)
#define L_MAXLENNUM 200
#endif
static const char *l_str2dloc (const char *s, lua_Number *result, int mode) {
char *endptr;
*result = (mode == 'x') ? lua_strx2number(s, &endptr) /* try to convert */
: lua_str2number(s, &endptr);
if (endptr == s) return NULL; /* nothing recognized? */
while (lisspace(cast_uchar(*endptr))) endptr++; /* skip trailing spaces */
return (*endptr == '\0') ? endptr : NULL; /* OK if no trailing characters */
}
/*
** Convert string 's' to a Lua number (put in 'result'). Return NULL
** on fail or the address of the ending '\0' on success.
** 'pmode' points to (and 'mode' contains) special things in the string:
** - 'x'/'X' means an hexadecimal numeral
** - 'n'/'N' means 'inf' or 'nan' (which should be rejected)
** - '.' just optimizes the search for the common case (nothing special)
** This function accepts both the current locale or a dot as the radix
** mark. If the convertion fails, it may mean number has a dot but
** locale accepts something else. In that case, the code copies 's'
** to a buffer (because 's' is read-only), changes the dot to the
** current locale radix mark, and tries to convert again.
*/
static const char *l_str2d (const char *s, lua_Number *result) {
const char *endptr;
const char *pmode = strpbrk(s, ".xXnN");
int mode = pmode ? ltolower(cast_uchar(*pmode)) : 0;
if (mode == 'n') /* reject 'inf' and 'nan' */
return NULL;
endptr = l_str2dloc(s, result, mode); /* try to convert */
if (endptr == NULL) { /* failed? may be a different locale */
char buff[L_MAXLENNUM + 1];
char *pdot = strchr(s, '.');
if (strlen(s) > L_MAXLENNUM || pdot == NULL)
return NULL; /* string too long or no dot; fail */
strcpy(buff, s); /* copy string to buffer */
buff[pdot - s] = lua_getlocaledecpoint(); /* correct decimal point */
endptr = l_str2dloc(buff, result, mode); /* try again */
if (endptr != NULL)
endptr = s + (endptr - buff); /* make relative to 's' */
}
return endptr;
}
#define MAXBY10 cast(lua_Unsigned, LUA_MAXINTEGER / 10)
#define MAXLASTD cast_int(LUA_MAXINTEGER % 10)
static const char *l_str2int (const char *s, lua_Integer *result) {
lua_Unsigned a = 0;
int empty = 1;
int neg;
while (lisspace(cast_uchar(*s))) s++; /* skip initial spaces */
neg = isneg(&s);
if (s[0] == '0' &&
(s[1] == 'x' || s[1] == 'X')) { /* hex? */
s += 2; /* skip '0x' */
for (; lisxdigit(cast_uchar(*s)); s++) {
a = a * 16 + luaO_hexavalue(*s);
empty = 0;
}
}
else { /* decimal */
for (; lisdigit(cast_uchar(*s)); s++) {
int d = *s - '0';
if (a >= MAXBY10 && (a > MAXBY10 || d > MAXLASTD + neg)) /* overflow? */
return NULL; /* do not accept it (as integer) */
a = a * 10 + d;
empty = 0;
}
}
while (lisspace(cast_uchar(*s))) s++; /* skip trailing spaces */
if (empty || *s != '\0') return NULL; /* something wrong in the numeral */
else {
*result = l_castU2S((neg) ? 0u - a : a);
return s;
}
}
size_t luaO_str2num (const char *s, TValue *o) {
lua_Integer i; lua_Number n;
const char *e;
if ((e = l_str2int(s, &i)) != NULL) { /* try as an integer */
setivalue(o, i);
}
else if ((e = l_str2d(s, &n)) != NULL) { /* else try as a float */
setfltvalue(o, n);
}
else
return 0; /* conversion failed */
return (e - s) + 1; /* success; return string size */
}
int luaO_utf8esc (char *buff, unsigned long x) {
int n = 1; /* number of bytes put in buffer (backwards) */
lua_assert(x <= 0x10FFFF);
if (x < 0x80) /* ascii? */
buff[UTF8BUFFSZ - 1] = cast(char, x);
else { /* need continuation bytes */
unsigned int mfb = 0x3f; /* maximum that fits in first byte */
do { /* add continuation bytes */
buff[UTF8BUFFSZ - (n++)] = cast(char, 0x80 | (x & 0x3f));
x >>= 6; /* remove added bits */
mfb >>= 1; /* now there is one less bit available in first byte */
} while (x > mfb); /* still needs continuation byte? */
buff[UTF8BUFFSZ - n] = cast(char, (~mfb << 1) | x); /* add first byte */
}
return n;
}
/* maximum length of the conversion of a number to a string */
#define MAXNUMBER2STR 50
/*
** Convert a number object to a string
*/
void luaO_tostring (lua_State *L, StkId obj) {
char buff[MAXNUMBER2STR];
size_t len;
lua_assert(ttisnumber(obj));
if (ttisinteger(obj))
len = lua_integer2str(buff, sizeof(buff), ivalue(obj));
else {
len = lua_number2str(buff, sizeof(buff), fltvalue(obj));
#if !defined(LUA_COMPAT_FLOATSTRING)
if (buff[strspn(buff, "-0123456789")] == '\0') { /* looks like an int? */
buff[len++] = lua_getlocaledecpoint();
buff[len++] = '0'; /* adds '.0' to result */
}
#endif
}
setsvalue2s(L, obj, luaS_newlstr(L, buff, len));
}
static void pushstr (lua_State *L, const char *str, size_t l) {
setsvalue2s(L, L->top, luaS_newlstr(L, str, l));
luaD_inctop(L);
}
/*
** this function handles only '%d', '%c', '%f', '%p', and '%s'
conventional formats, plus Lua-specific '%I' and '%U'
*/
const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
int n = 0;
for (;;) {
const char *e = strchr(fmt, '%');
if (e == NULL) break;
pushstr(L, fmt, e - fmt);
switch (*(e+1)) {
case 's': { /* zero-terminated string */
const char *s = va_arg(argp, char *);
if (s == NULL) s = "(null)";
pushstr(L, s, strlen(s));
break;
}
case 'c': { /* an 'int' as a character */
char buff = cast(char, va_arg(argp, int));
if (lisprint(cast_uchar(buff)))
pushstr(L, &buff, 1);
else /* non-printable character; print its code */
luaO_pushfstring(L, "<\\%d>", cast_uchar(buff));
break;
}
case 'd': { /* an 'int' */
setivalue(L->top, va_arg(argp, int));
goto top2str;
}
case 'I': { /* a 'lua_Integer' */
setivalue(L->top, cast(lua_Integer, va_arg(argp, l_uacInt)));
goto top2str;
}
case 'f': { /* a 'lua_Number' */
setfltvalue(L->top, cast_num(va_arg(argp, l_uacNumber)));
top2str: /* convert the top element to a string */
luaD_inctop(L);
luaO_tostring(L, L->top - 1);
break;
}
case 'p': { /* a pointer */
char buff[4*sizeof(void *) + 8]; /* should be enough space for a '%p' */
int l = l_sprintf(buff, sizeof(buff), "%p", va_arg(argp, void *));
pushstr(L, buff, l);
break;
}
case 'U': { /* an 'int' as a UTF-8 sequence */
char buff[UTF8BUFFSZ];
int l = luaO_utf8esc(buff, cast(long, va_arg(argp, long)));
pushstr(L, buff + UTF8BUFFSZ - l, l);
break;
}
case '%': {
pushstr(L, "%", 1);
break;
}
default: {
luaG_runerror(L, "invalid option '%%%c' to 'lua_pushfstring'",
*(e + 1));
}
}
n += 2;
fmt = e+2;
}
luaD_checkstack(L, 1);
pushstr(L, fmt, strlen(fmt));
if (n > 0) luaV_concat(L, n + 1);
return svalue(L->top - 1);
}
const char *luaO_pushfstring (lua_State *L, const char *fmt, ...) {
const char *msg;
va_list argp;
va_start(argp, fmt);
msg = luaO_pushvfstring(L, fmt, argp);
va_end(argp);
return msg;
}
/* number of chars of a literal string without the ending \0 */
#define LL(x) (sizeof(x)/sizeof(char) - 1)
#define RETS "..."
#define PRE "[string \""
#define POS "\"]"
#define addstr(a,b,l) ( memcpy(a,b,(l) * sizeof(char)), a += (l) )
void luaO_chunkid (char *out, const char *source, size_t bufflen) {
size_t l = strlen(source);
if (*source == '=') { /* 'literal' source */
if (l <= bufflen) /* small enough? */
memcpy(out, source + 1, l * sizeof(char));
else { /* truncate it */
addstr(out, source + 1, bufflen - 1);
*out = '\0';
}
}
else if (*source == '@') { /* file name */
if (l <= bufflen) /* small enough? */
memcpy(out, source + 1, l * sizeof(char));
else { /* add '...' before rest of name */
addstr(out, RETS, LL(RETS));
bufflen -= LL(RETS);
memcpy(out, source + 1 + l - bufflen, bufflen * sizeof(char));
}
}
else { /* string; format as [string "source"] */
const char *nl = strchr(source, '\n'); /* find first new line (if any) */
addstr(out, PRE, LL(PRE)); /* add prefix */
bufflen -= LL(PRE RETS POS) + 1; /* save space for prefix+suffix+'\0' */
if (l < bufflen && nl == NULL) { /* small one-line source? */
addstr(out, source, l); /* keep it */
}
else {
if (nl != NULL) l = nl - source; /* stop at first newline */
if (l > bufflen) l = bufflen;
addstr(out, source, l);
addstr(out, RETS, LL(RETS));
}
memcpy(out, POS, (LL(POS) + 1) * sizeof(char));
}
}

549
deps/lua/lobject.h vendored Normal file
View File

@@ -0,0 +1,549 @@
/*
** $Id: lobject.h,v 2.116 2015/11/03 18:33:10 roberto Exp $
** Type definitions for Lua objects
** See Copyright Notice in lua.h
*/
#ifndef lobject_h
#define lobject_h
#include <stdarg.h>
#include "llimits.h"
#include "lua.h"
/*
** Extra tags for non-values
*/
#define LUA_TPROTO LUA_NUMTAGS /* function prototypes */
#define LUA_TDEADKEY (LUA_NUMTAGS+1) /* removed keys in tables */
/*
** number of all possible tags (including LUA_TNONE but excluding DEADKEY)
*/
#define LUA_TOTALTAGS (LUA_TPROTO + 2)
/*
** tags for Tagged Values have the following use of bits:
** bits 0-3: actual tag (a LUA_T* value)
** bits 4-5: variant bits
** bit 6: whether value is collectable
*/
/*
** LUA_TFUNCTION variants:
** 0 - Lua function
** 1 - light C function
** 2 - regular C function (closure)
*/
/* Variant tags for functions */
#define LUA_TLCL (LUA_TFUNCTION | (0 << 4)) /* Lua closure */
#define LUA_TLCF (LUA_TFUNCTION | (1 << 4)) /* light C function */
#define LUA_TCCL (LUA_TFUNCTION | (2 << 4)) /* C closure */
/* Variant tags for strings */
#define LUA_TSHRSTR (LUA_TSTRING | (0 << 4)) /* short strings */
#define LUA_TLNGSTR (LUA_TSTRING | (1 << 4)) /* long strings */
/* Variant tags for numbers */
#define LUA_TNUMFLT (LUA_TNUMBER | (0 << 4)) /* float numbers */
#define LUA_TNUMINT (LUA_TNUMBER | (1 << 4)) /* integer numbers */
/* Bit mark for collectable types */
#define BIT_ISCOLLECTABLE (1 << 6)
/* mark a tag as collectable */
#define ctb(t) ((t) | BIT_ISCOLLECTABLE)
/*
** Common type for all collectable objects
*/
typedef struct GCObject GCObject;
/*
** Common Header for all collectable objects (in macro form, to be
** included in other objects)
*/
#define CommonHeader GCObject *next; lu_byte tt; lu_byte marked
/*
** Common type has only the common header
*/
struct GCObject {
CommonHeader;
};
/*
** Tagged Values. This is the basic representation of values in Lua,
** an actual value plus a tag with its type.
*/
/*
** Union of all Lua values
*/
typedef union Value {
GCObject *gc; /* collectable objects */
void *p; /* light userdata */
int b; /* booleans */
lua_CFunction f; /* light C functions */
lua_Integer i; /* integer numbers */
lua_Number n; /* float numbers */
} Value;
#define TValuefields Value value_; int tt_
typedef struct lua_TValue {
TValuefields;
} TValue;
/* macro defining a nil value */
#define NILCONSTANT {NULL}, LUA_TNIL
#define val_(o) ((o)->value_)
/* raw type tag of a TValue */
#define rttype(o) ((o)->tt_)
/* tag with no variants (bits 0-3) */
#define novariant(x) ((x) & 0x0F)
/* type tag of a TValue (bits 0-3 for tags + variant bits 4-5) */
#define ttype(o) (rttype(o) & 0x3F)
/* type tag of a TValue with no variants (bits 0-3) */
#define ttnov(o) (novariant(rttype(o)))
/* Macros to test type */
#define checktag(o,t) (rttype(o) == (t))
#define checktype(o,t) (ttnov(o) == (t))
#define ttisnumber(o) checktype((o), LUA_TNUMBER)
#define ttisfloat(o) checktag((o), LUA_TNUMFLT)
#define ttisinteger(o) checktag((o), LUA_TNUMINT)
#define ttisnil(o) checktag((o), LUA_TNIL)
#define ttisboolean(o) checktag((o), LUA_TBOOLEAN)
#define ttislightuserdata(o) checktag((o), LUA_TLIGHTUSERDATA)
#define ttisstring(o) checktype((o), LUA_TSTRING)
#define ttisshrstring(o) checktag((o), ctb(LUA_TSHRSTR))
#define ttislngstring(o) checktag((o), ctb(LUA_TLNGSTR))
#define ttistable(o) checktag((o), ctb(LUA_TTABLE))
#define ttisfunction(o) checktype(o, LUA_TFUNCTION)
#define ttisclosure(o) ((rttype(o) & 0x1F) == LUA_TFUNCTION)
#define ttisCclosure(o) checktag((o), ctb(LUA_TCCL))
#define ttisLclosure(o) checktag((o), ctb(LUA_TLCL))
#define ttislcf(o) checktag((o), LUA_TLCF)
#define ttisfulluserdata(o) checktag((o), ctb(LUA_TUSERDATA))
#define ttisthread(o) checktag((o), ctb(LUA_TTHREAD))
#define ttisdeadkey(o) checktag((o), LUA_TDEADKEY)
/* Macros to access values */
#define ivalue(o) check_exp(ttisinteger(o), val_(o).i)
#define fltvalue(o) check_exp(ttisfloat(o), val_(o).n)
#define nvalue(o) check_exp(ttisnumber(o), \
(ttisinteger(o) ? cast_num(ivalue(o)) : fltvalue(o)))
#define gcvalue(o) check_exp(iscollectable(o), val_(o).gc)
#define pvalue(o) check_exp(ttislightuserdata(o), val_(o).p)
#define tsvalue(o) check_exp(ttisstring(o), gco2ts(val_(o).gc))
#define uvalue(o) check_exp(ttisfulluserdata(o), gco2u(val_(o).gc))
#define clvalue(o) check_exp(ttisclosure(o), gco2cl(val_(o).gc))
#define clLvalue(o) check_exp(ttisLclosure(o), gco2lcl(val_(o).gc))
#define clCvalue(o) check_exp(ttisCclosure(o), gco2ccl(val_(o).gc))
#define fvalue(o) check_exp(ttislcf(o), val_(o).f)
#define hvalue(o) check_exp(ttistable(o), gco2t(val_(o).gc))
#define bvalue(o) check_exp(ttisboolean(o), val_(o).b)
#define thvalue(o) check_exp(ttisthread(o), gco2th(val_(o).gc))
/* a dead value may get the 'gc' field, but cannot access its contents */
#define deadvalue(o) check_exp(ttisdeadkey(o), cast(void *, val_(o).gc))
#define l_isfalse(o) (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0))
#define iscollectable(o) (rttype(o) & BIT_ISCOLLECTABLE)
/* Macros for internal tests */
#define righttt(obj) (ttype(obj) == gcvalue(obj)->tt)
#define checkliveness(L,obj) \
lua_longassert(!iscollectable(obj) || \
(righttt(obj) && (L == NULL || !isdead(G(L),gcvalue(obj)))))
/* Macros to set values */
#define settt_(o,t) ((o)->tt_=(t))
#define setfltvalue(obj,x) \
{ TValue *io=(obj); val_(io).n=(x); settt_(io, LUA_TNUMFLT); }
#define chgfltvalue(obj,x) \
{ TValue *io=(obj); lua_assert(ttisfloat(io)); val_(io).n=(x); }
#define setivalue(obj,x) \
{ TValue *io=(obj); val_(io).i=(x); settt_(io, LUA_TNUMINT); }
#define chgivalue(obj,x) \
{ TValue *io=(obj); lua_assert(ttisinteger(io)); val_(io).i=(x); }
#define setnilvalue(obj) settt_(obj, LUA_TNIL)
#define setfvalue(obj,x) \
{ TValue *io=(obj); val_(io).f=(x); settt_(io, LUA_TLCF); }
#define setpvalue(obj,x) \
{ TValue *io=(obj); val_(io).p=(x); settt_(io, LUA_TLIGHTUSERDATA); }
#define setbvalue(obj,x) \
{ TValue *io=(obj); val_(io).b=(x); settt_(io, LUA_TBOOLEAN); }
#define setgcovalue(L,obj,x) \
{ TValue *io = (obj); GCObject *i_g=(x); \
val_(io).gc = i_g; settt_(io, ctb(i_g->tt)); }
#define setsvalue(L,obj,x) \
{ TValue *io = (obj); TString *x_ = (x); \
val_(io).gc = obj2gco(x_); settt_(io, ctb(x_->tt)); \
checkliveness(L,io); }
#define setuvalue(L,obj,x) \
{ TValue *io = (obj); Udata *x_ = (x); \
val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TUSERDATA)); \
checkliveness(L,io); }
#define setthvalue(L,obj,x) \
{ TValue *io = (obj); lua_State *x_ = (x); \
val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TTHREAD)); \
checkliveness(L,io); }
#define setclLvalue(L,obj,x) \
{ TValue *io = (obj); LClosure *x_ = (x); \
val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TLCL)); \
checkliveness(L,io); }
#define setclCvalue(L,obj,x) \
{ TValue *io = (obj); CClosure *x_ = (x); \
val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TCCL)); \
checkliveness(L,io); }
#define sethvalue(L,obj,x) \
{ TValue *io = (obj); Table *x_ = (x); \
val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TTABLE)); \
checkliveness(L,io); }
#define setdeadvalue(obj) settt_(obj, LUA_TDEADKEY)
#define setobj(L,obj1,obj2) \
{ TValue *io1=(obj1); *io1 = *(obj2); \
(void)L; checkliveness(L,io1); }
/*
** different types of assignments, according to destination
*/
/* from stack to (same) stack */
#define setobjs2s setobj
/* to stack (not from same stack) */
#define setobj2s setobj
#define setsvalue2s setsvalue
#define sethvalue2s sethvalue
#define setptvalue2s setptvalue
/* from table to same table */
#define setobjt2t setobj
/* to new object */
#define setobj2n setobj
#define setsvalue2n setsvalue
/* to table (define it as an expression to be used in macros) */
#define setobj2t(L,o1,o2) ((void)L, *(o1)=*(o2), checkliveness(L,(o1)))
/*
** {======================================================
** types and prototypes
** =======================================================
*/
typedef TValue *StkId; /* index to stack elements */
/*
** Header for string value; string bytes follow the end of this structure
** (aligned according to 'UTString'; see next).
*/
typedef struct TString {
CommonHeader;
lu_byte extra; /* reserved words for short strings; "has hash" for longs */
lu_byte shrlen; /* length for short strings */
unsigned int hash;
union {
size_t lnglen; /* length for long strings */
struct TString *hnext; /* linked list for hash table */
} u;
} TString;
/*
** Ensures that address after this type is always fully aligned.
*/
typedef union UTString {
L_Umaxalign dummy; /* ensures maximum alignment for strings */
TString tsv;
} UTString;
/*
** Get the actual string (array of bytes) from a 'TString'.
** (Access to 'extra' ensures that value is really a 'TString'.)
*/
#define getstr(ts) \
check_exp(sizeof((ts)->extra), cast(char *, (ts)) + sizeof(UTString))
/* get the actual string (array of bytes) from a Lua value */
#define svalue(o) getstr(tsvalue(o))
/* get string length from 'TString *s' */
#define tsslen(s) ((s)->tt == LUA_TSHRSTR ? (s)->shrlen : (s)->u.lnglen)
/* get string length from 'TValue *o' */
#define vslen(o) tsslen(tsvalue(o))
/*
** Header for userdata; memory area follows the end of this structure
** (aligned according to 'UUdata'; see next).
*/
typedef struct Udata {
CommonHeader;
lu_byte ttuv_; /* user value's tag */
struct Table *metatable;
size_t len; /* number of bytes */
union Value user_; /* user value */
} Udata;
/*
** Ensures that address after this type is always fully aligned.
*/
typedef union UUdata {
L_Umaxalign dummy; /* ensures maximum alignment for 'local' udata */
Udata uv;
} UUdata;
/*
** Get the address of memory block inside 'Udata'.
** (Access to 'ttuv_' ensures that value is really a 'Udata'.)
*/
#define getudatamem(u) \
check_exp(sizeof((u)->ttuv_), (cast(char*, (u)) + sizeof(UUdata)))
#define setuservalue(L,u,o) \
{ const TValue *io=(o); Udata *iu = (u); \
iu->user_ = io->value_; iu->ttuv_ = rttype(io); \
checkliveness(L,io); }
#define getuservalue(L,u,o) \
{ TValue *io=(o); const Udata *iu = (u); \
io->value_ = iu->user_; settt_(io, iu->ttuv_); \
checkliveness(L,io); }
/*
** Description of an upvalue for function prototypes
*/
typedef struct Upvaldesc {
TString *name; /* upvalue name (for debug information) */
lu_byte instack; /* whether it is in stack (register) */
lu_byte idx; /* index of upvalue (in stack or in outer function's list) */
} Upvaldesc;
/*
** Description of a local variable for function prototypes
** (used for debug information)
*/
typedef struct LocVar {
TString *varname;
int startpc; /* first point where variable is active */
int endpc; /* first point where variable is dead */
} LocVar;
/*
** Function Prototypes
*/
typedef struct Proto {
CommonHeader;
lu_byte numparams; /* number of fixed parameters */
lu_byte is_vararg; /* 2: declared vararg; 1: uses vararg */
lu_byte maxstacksize; /* number of registers needed by this function */
int sizeupvalues; /* size of 'upvalues' */
int sizek; /* size of 'k' */
int sizecode;
int sizelineinfo;
int sizep; /* size of 'p' */
int sizelocvars;
int linedefined; /* debug information */
int lastlinedefined; /* debug information */
TValue *k; /* constants used by the function */
Instruction *code; /* opcodes */
struct Proto **p; /* functions defined inside the function */
int *lineinfo; /* map from opcodes to source lines (debug information) */
LocVar *locvars; /* information about local variables (debug information) */
Upvaldesc *upvalues; /* upvalue information */
struct LClosure *cache; /* last-created closure with this prototype */
TString *source; /* used for debug information */
GCObject *gclist;
} Proto;
/*
** Lua Upvalues
*/
typedef struct UpVal UpVal;
/*
** Closures
*/
#define ClosureHeader \
CommonHeader; lu_byte nupvalues; GCObject *gclist
typedef struct CClosure {
ClosureHeader;
lua_CFunction f;
TValue upvalue[1]; /* list of upvalues */
} CClosure;
typedef struct LClosure {
ClosureHeader;
struct Proto *p;
UpVal *upvals[1]; /* list of upvalues */
} LClosure;
typedef union Closure {
CClosure c;
LClosure l;
} Closure;
#define isLfunction(o) ttisLclosure(o)
#define getproto(o) (clLvalue(o)->p)
/*
** Tables
*/
typedef union TKey {
struct {
TValuefields;
int next; /* for chaining (offset for next node) */
} nk;
TValue tvk;
} TKey;
/* copy a value into a key without messing up field 'next' */
#define setnodekey(L,key,obj) \
{ TKey *k_=(key); const TValue *io_=(obj); \
k_->nk.value_ = io_->value_; k_->nk.tt_ = io_->tt_; \
(void)L; checkliveness(L,io_); }
typedef struct Node {
TValue i_val;
TKey i_key;
} Node;
typedef struct Table {
CommonHeader;
lu_byte flags; /* 1<<p means tagmethod(p) is not present */
lu_byte lsizenode; /* log2 of size of 'node' array */
unsigned int sizearray; /* size of 'array' array */
TValue *array; /* array part */
Node *node;
Node *lastfree; /* any free position is before this position */
struct Table *metatable;
GCObject *gclist;
} Table;
/*
** 'module' operation for hashing (size is always a power of 2)
*/
#define lmod(s,size) \
(check_exp((size&(size-1))==0, (cast(int, (s) & ((size)-1)))))
#define twoto(x) (1<<(x))
#define sizenode(t) (twoto((t)->lsizenode))
/*
** (address of) a fixed nil value
*/
#define luaO_nilobject (&luaO_nilobject_)
LUAI_DDEC const TValue luaO_nilobject_;
/* size of buffer for 'luaO_utf8esc' function */
#define UTF8BUFFSZ 8
LUAI_FUNC int luaO_int2fb (unsigned int x);
LUAI_FUNC int luaO_fb2int (int x);
LUAI_FUNC int luaO_utf8esc (char *buff, unsigned long x);
LUAI_FUNC int luaO_ceillog2 (unsigned int x);
LUAI_FUNC void luaO_arith (lua_State *L, int op, const TValue *p1,
const TValue *p2, TValue *res);
LUAI_FUNC size_t luaO_str2num (const char *s, TValue *o);
LUAI_FUNC int luaO_hexavalue (int c);
LUAI_FUNC void luaO_tostring (lua_State *L, StkId obj);
LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt,
va_list argp);
LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...);
LUAI_FUNC void luaO_chunkid (char *out, const char *source, size_t len);
#endif

124
deps/lua/lopcodes.c vendored Normal file
View File

@@ -0,0 +1,124 @@
/*
** $Id: lopcodes.c,v 1.55 2015/01/05 13:48:33 roberto Exp $
** Opcodes for Lua virtual machine
** See Copyright Notice in lua.h
*/
#define lopcodes_c
#define LUA_CORE
#include "lprefix.h"
#include <stddef.h>
#include "lopcodes.h"
/* ORDER OP */
LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = {
"MOVE",
"LOADK",
"LOADKX",
"LOADBOOL",
"LOADNIL",
"GETUPVAL",
"GETTABUP",
"GETTABLE",
"SETTABUP",
"SETUPVAL",
"SETTABLE",
"NEWTABLE",
"SELF",
"ADD",
"SUB",
"MUL",
"MOD",
"POW",
"DIV",
"IDIV",
"BAND",
"BOR",
"BXOR",
"SHL",
"SHR",
"UNM",
"BNOT",
"NOT",
"LEN",
"CONCAT",
"JMP",
"EQ",
"LT",
"LE",
"TEST",
"TESTSET",
"CALL",
"TAILCALL",
"RETURN",
"FORLOOP",
"FORPREP",
"TFORCALL",
"TFORLOOP",
"SETLIST",
"CLOSURE",
"VARARG",
"EXTRAARG",
NULL
};
#define opmode(t,a,b,c,m) (((t)<<7) | ((a)<<6) | ((b)<<4) | ((c)<<2) | (m))
LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = {
/* T A B C mode opcode */
opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_MOVE */
,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_LOADK */
,opmode(0, 1, OpArgN, OpArgN, iABx) /* OP_LOADKX */
,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_LOADBOOL */
,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_LOADNIL */
,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_GETUPVAL */
,opmode(0, 1, OpArgU, OpArgK, iABC) /* OP_GETTABUP */
,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_GETTABLE */
,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABUP */
,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_SETUPVAL */
,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABLE */
,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_NEWTABLE */
,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_SELF */
,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_ADD */
,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SUB */
,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MUL */
,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MOD */
,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_POW */
,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_DIV */
,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_IDIV */
,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_BAND */
,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_BOR */
,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_BXOR */
,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SHL */
,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SHR */
,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_UNM */
,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_BNOT */
,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_NOT */
,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LEN */
,opmode(0, 1, OpArgR, OpArgR, iABC) /* OP_CONCAT */
,opmode(0, 0, OpArgR, OpArgN, iAsBx) /* OP_JMP */
,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_EQ */
,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LT */
,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LE */
,opmode(1, 0, OpArgN, OpArgU, iABC) /* OP_TEST */
,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TESTSET */
,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_CALL */
,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_TAILCALL */
,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_RETURN */
,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORLOOP */
,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORPREP */
,opmode(0, 0, OpArgN, OpArgU, iABC) /* OP_TFORCALL */
,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_TFORLOOP */
,opmode(0, 0, OpArgU, OpArgU, iABC) /* OP_SETLIST */
,opmode(0, 1, OpArgU, OpArgN, iABx) /* OP_CLOSURE */
,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_VARARG */
,opmode(0, 0, OpArgU, OpArgU, iAx) /* OP_EXTRAARG */
};

295
deps/lua/lopcodes.h vendored Normal file
View File

@@ -0,0 +1,295 @@
/*
** $Id: lopcodes.h,v 1.148 2014/10/25 11:50:46 roberto Exp $
** Opcodes for Lua virtual machine
** See Copyright Notice in lua.h
*/
#ifndef lopcodes_h
#define lopcodes_h
#include "llimits.h"
/*===========================================================================
We assume that instructions are unsigned numbers.
All instructions have an opcode in the first 6 bits.
Instructions can have the following fields:
'A' : 8 bits
'B' : 9 bits
'C' : 9 bits
'Ax' : 26 bits ('A', 'B', and 'C' together)
'Bx' : 18 bits ('B' and 'C' together)
'sBx' : signed Bx
A signed argument is represented in excess K; that is, the number
value is the unsigned value minus K. K is exactly the maximum value
for that argument (so that -max is represented by 0, and +max is
represented by 2*max), which is half the maximum for the corresponding
unsigned argument.
===========================================================================*/
enum OpMode {iABC, iABx, iAsBx, iAx}; /* basic instruction format */
/*
** size and position of opcode arguments.
*/
#define SIZE_C 9
#define SIZE_B 9
#define SIZE_Bx (SIZE_C + SIZE_B)
#define SIZE_A 8
#define SIZE_Ax (SIZE_C + SIZE_B + SIZE_A)
#define SIZE_OP 6
#define POS_OP 0
#define POS_A (POS_OP + SIZE_OP)
#define POS_C (POS_A + SIZE_A)
#define POS_B (POS_C + SIZE_C)
#define POS_Bx POS_C
#define POS_Ax POS_A
/*
** limits for opcode arguments.
** we use (signed) int to manipulate most arguments,
** so they must fit in LUAI_BITSINT-1 bits (-1 for sign)
*/
#if SIZE_Bx < LUAI_BITSINT-1
#define MAXARG_Bx ((1<<SIZE_Bx)-1)
#define MAXARG_sBx (MAXARG_Bx>>1) /* 'sBx' is signed */
#else
#define MAXARG_Bx MAX_INT
#define MAXARG_sBx MAX_INT
#endif
#if SIZE_Ax < LUAI_BITSINT-1
#define MAXARG_Ax ((1<<SIZE_Ax)-1)
#else
#define MAXARG_Ax MAX_INT
#endif
#define MAXARG_A ((1<<SIZE_A)-1)
#define MAXARG_B ((1<<SIZE_B)-1)
#define MAXARG_C ((1<<SIZE_C)-1)
/* creates a mask with 'n' 1 bits at position 'p' */
#define MASK1(n,p) ((~((~(Instruction)0)<<(n)))<<(p))
/* creates a mask with 'n' 0 bits at position 'p' */
#define MASK0(n,p) (~MASK1(n,p))
/*
** the following macros help to manipulate instructions
*/
#define GET_OPCODE(i) (cast(OpCode, ((i)>>POS_OP) & MASK1(SIZE_OP,0)))
#define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \
((cast(Instruction, o)<<POS_OP)&MASK1(SIZE_OP,POS_OP))))
#define getarg(i,pos,size) (cast(int, ((i)>>pos) & MASK1(size,0)))
#define setarg(i,v,pos,size) ((i) = (((i)&MASK0(size,pos)) | \
((cast(Instruction, v)<<pos)&MASK1(size,pos))))
#define GETARG_A(i) getarg(i, POS_A, SIZE_A)
#define SETARG_A(i,v) setarg(i, v, POS_A, SIZE_A)
#define GETARG_B(i) getarg(i, POS_B, SIZE_B)
#define SETARG_B(i,v) setarg(i, v, POS_B, SIZE_B)
#define GETARG_C(i) getarg(i, POS_C, SIZE_C)
#define SETARG_C(i,v) setarg(i, v, POS_C, SIZE_C)
#define GETARG_Bx(i) getarg(i, POS_Bx, SIZE_Bx)
#define SETARG_Bx(i,v) setarg(i, v, POS_Bx, SIZE_Bx)
#define GETARG_Ax(i) getarg(i, POS_Ax, SIZE_Ax)
#define SETARG_Ax(i,v) setarg(i, v, POS_Ax, SIZE_Ax)
#define GETARG_sBx(i) (GETARG_Bx(i)-MAXARG_sBx)
#define SETARG_sBx(i,b) SETARG_Bx((i),cast(unsigned int, (b)+MAXARG_sBx))
#define CREATE_ABC(o,a,b,c) ((cast(Instruction, o)<<POS_OP) \
| (cast(Instruction, a)<<POS_A) \
| (cast(Instruction, b)<<POS_B) \
| (cast(Instruction, c)<<POS_C))
#define CREATE_ABx(o,a,bc) ((cast(Instruction, o)<<POS_OP) \
| (cast(Instruction, a)<<POS_A) \
| (cast(Instruction, bc)<<POS_Bx))
#define CREATE_Ax(o,a) ((cast(Instruction, o)<<POS_OP) \
| (cast(Instruction, a)<<POS_Ax))
/*
** Macros to operate RK indices
*/
/* this bit 1 means constant (0 means register) */
#define BITRK (1 << (SIZE_B - 1))
/* test whether value is a constant */
#define ISK(x) ((x) & BITRK)
/* gets the index of the constant */
#define INDEXK(r) ((int)(r) & ~BITRK)
#define MAXINDEXRK (BITRK - 1)
/* code a constant index as a RK value */
#define RKASK(x) ((x) | BITRK)
/*
** invalid register that fits in 8 bits
*/
#define NO_REG MAXARG_A
/*
** R(x) - register
** Kst(x) - constant (in constant table)
** RK(x) == if ISK(x) then Kst(INDEXK(x)) else R(x)
*/
/*
** grep "ORDER OP" if you change these enums
*/
typedef enum {
/*----------------------------------------------------------------------
name args description
------------------------------------------------------------------------*/
OP_MOVE,/* A B R(A) := R(B) */
OP_LOADK,/* A Bx R(A) := Kst(Bx) */
OP_LOADKX,/* A R(A) := Kst(extra arg) */
OP_LOADBOOL,/* A B C R(A) := (Bool)B; if (C) pc++ */
OP_LOADNIL,/* A B R(A), R(A+1), ..., R(A+B) := nil */
OP_GETUPVAL,/* A B R(A) := UpValue[B] */
OP_GETTABUP,/* A B C R(A) := UpValue[B][RK(C)] */
OP_GETTABLE,/* A B C R(A) := R(B)[RK(C)] */
OP_SETTABUP,/* A B C UpValue[A][RK(B)] := RK(C) */
OP_SETUPVAL,/* A B UpValue[B] := R(A) */
OP_SETTABLE,/* A B C R(A)[RK(B)] := RK(C) */
OP_NEWTABLE,/* A B C R(A) := {} (size = B,C) */
OP_SELF,/* A B C R(A+1) := R(B); R(A) := R(B)[RK(C)] */
OP_ADD,/* A B C R(A) := RK(B) + RK(C) */
OP_SUB,/* A B C R(A) := RK(B) - RK(C) */
OP_MUL,/* A B C R(A) := RK(B) * RK(C) */
OP_MOD,/* A B C R(A) := RK(B) % RK(C) */
OP_POW,/* A B C R(A) := RK(B) ^ RK(C) */
OP_DIV,/* A B C R(A) := RK(B) / RK(C) */
OP_IDIV,/* A B C R(A) := RK(B) // RK(C) */
OP_BAND,/* A B C R(A) := RK(B) & RK(C) */
OP_BOR,/* A B C R(A) := RK(B) | RK(C) */
OP_BXOR,/* A B C R(A) := RK(B) ~ RK(C) */
OP_SHL,/* A B C R(A) := RK(B) << RK(C) */
OP_SHR,/* A B C R(A) := RK(B) >> RK(C) */
OP_UNM,/* A B R(A) := -R(B) */
OP_BNOT,/* A B R(A) := ~R(B) */
OP_NOT,/* A B R(A) := not R(B) */
OP_LEN,/* A B R(A) := length of R(B) */
OP_CONCAT,/* A B C R(A) := R(B).. ... ..R(C) */
OP_JMP,/* A sBx pc+=sBx; if (A) close all upvalues >= R(A - 1) */
OP_EQ,/* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */
OP_LT,/* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */
OP_LE,/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */
OP_TEST,/* A C if not (R(A) <=> C) then pc++ */
OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */
OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */
OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */
OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */
OP_FORLOOP,/* A sBx R(A)+=R(A+2);
if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }*/
OP_FORPREP,/* A sBx R(A)-=R(A+2); pc+=sBx */
OP_TFORCALL,/* A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); */
OP_TFORLOOP,/* A sBx if R(A+1) ~= nil then { R(A)=R(A+1); pc += sBx }*/
OP_SETLIST,/* A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B */
OP_CLOSURE,/* A Bx R(A) := closure(KPROTO[Bx]) */
OP_VARARG,/* A B R(A), R(A+1), ..., R(A+B-2) = vararg */
OP_EXTRAARG/* Ax extra (larger) argument for previous opcode */
} OpCode;
#define NUM_OPCODES (cast(int, OP_EXTRAARG) + 1)
/*===========================================================================
Notes:
(*) In OP_CALL, if (B == 0) then B = top. If (C == 0), then 'top' is
set to last_result+1, so next open instruction (OP_CALL, OP_RETURN,
OP_SETLIST) may use 'top'.
(*) In OP_VARARG, if (B == 0) then use actual number of varargs and
set top (like in OP_CALL with C == 0).
(*) In OP_RETURN, if (B == 0) then return up to 'top'.
(*) In OP_SETLIST, if (B == 0) then B = 'top'; if (C == 0) then next
'instruction' is EXTRAARG(real C).
(*) In OP_LOADKX, the next 'instruction' is always EXTRAARG.
(*) For comparisons, A specifies what condition the test should accept
(true or false).
(*) All 'skips' (pc++) assume that next instruction is a jump.
===========================================================================*/
/*
** masks for instruction properties. The format is:
** bits 0-1: op mode
** bits 2-3: C arg mode
** bits 4-5: B arg mode
** bit 6: instruction set register A
** bit 7: operator is a test (next instruction must be a jump)
*/
enum OpArgMask {
OpArgN, /* argument is not used */
OpArgU, /* argument is used */
OpArgR, /* argument is a register or a jump offset */
OpArgK /* argument is a constant or register/constant */
};
LUAI_DDEC const lu_byte luaP_opmodes[NUM_OPCODES];
#define getOpMode(m) (cast(enum OpMode, luaP_opmodes[m] & 3))
#define getBMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 4) & 3))
#define getCMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 2) & 3))
#define testAMode(m) (luaP_opmodes[m] & (1 << 6))
#define testTMode(m) (luaP_opmodes[m] & (1 << 7))
LUAI_DDEC const char *const luaP_opnames[NUM_OPCODES+1]; /* opcode names */
/* number of list items to accumulate before a SETLIST instruction */
#define LFIELDS_PER_FLUSH 50
#endif

403
deps/lua/loslib.c vendored Normal file
View File

@@ -0,0 +1,403 @@
/*
** $Id: loslib.c,v 1.64 2016/04/18 13:06:55 roberto Exp $
** Standard Operating System library
** See Copyright Notice in lua.h
*/
#define loslib_c
#define LUA_LIB
#include "lprefix.h"
#include <errno.h>
#include <locale.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
/*
** {==================================================================
** List of valid conversion specifiers for the 'strftime' function;
** options are grouped by length; group of length 2 start with '||'.
** ===================================================================
*/
#if !defined(LUA_STRFTIMEOPTIONS) /* { */
/* options for ANSI C 89 */
#define L_STRFTIMEC89 "aAbBcdHIjmMpSUwWxXyYZ%"
/* options for ISO C 99 and POSIX */
#define L_STRFTIMEC99 "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%" \
"||" "EcECExEXEyEY" "OdOeOHOIOmOMOSOuOUOVOwOWOy"
/* options for Windows */
#define L_STRFTIMEWIN "aAbBcdHIjmMpSUwWxXyYzZ%" \
"||" "#c#x#d#H#I#j#m#M#S#U#w#W#y#Y"
#if defined(LUA_USE_WINDOWS)
#define LUA_STRFTIMEOPTIONS L_STRFTIMEWIN
#elif defined(LUA_USE_C89)
#define LUA_STRFTIMEOPTIONS L_STRFTIMEC89
#else /* C99 specification */
#define LUA_STRFTIMEOPTIONS L_STRFTIMEC99
#endif
#endif /* } */
/* }================================================================== */
/*
** {==================================================================
** Configuration for time-related stuff
** ===================================================================
*/
#if !defined(l_time_t) /* { */
/*
** type to represent time_t in Lua
*/
#define l_timet lua_Integer
#define l_pushtime(L,t) lua_pushinteger(L,(lua_Integer)(t))
static time_t l_checktime (lua_State *L, int arg) {
lua_Integer t = luaL_checkinteger(L, arg);
luaL_argcheck(L, (time_t)t == t, arg, "time out-of-bounds");
return (time_t)t;
}
#endif /* } */
#if !defined(l_gmtime) /* { */
/*
** By default, Lua uses gmtime/localtime, except when POSIX is available,
** where it uses gmtime_r/localtime_r
*/
#if defined(LUA_USE_POSIX) /* { */
#define l_gmtime(t,r) gmtime_r(t,r)
#define l_localtime(t,r) localtime_r(t,r)
#else /* }{ */
/* ISO C definitions */
#define l_gmtime(t,r) ((void)(r)->tm_sec, gmtime(t))
#define l_localtime(t,r) ((void)(r)->tm_sec, localtime(t))
#endif /* } */
#endif /* } */
/* }================================================================== */
/*
** {==================================================================
** Configuration for 'tmpnam':
** By default, Lua uses tmpnam except when POSIX is available, where
** it uses mkstemp.
** ===================================================================
*/
#if !defined(lua_tmpnam) /* { */
#if defined(LUA_USE_POSIX) /* { */
#include <unistd.h>
#define LUA_TMPNAMBUFSIZE 32
#if !defined(LUA_TMPNAMTEMPLATE)
#define LUA_TMPNAMTEMPLATE "/tmp/lua_XXXXXX"
#endif
#define lua_tmpnam(b,e) { \
strcpy(b, LUA_TMPNAMTEMPLATE); \
e = mkstemp(b); \
if (e != -1) close(e); \
e = (e == -1); }
#else /* }{ */
/* ISO C definitions */
#define LUA_TMPNAMBUFSIZE L_tmpnam
#define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); }
#endif /* } */
#endif /* } */
/* }================================================================== */
static int os_execute (lua_State *L) {
const char *cmd = luaL_optstring(L, 1, NULL);
int stat = system(cmd);
if (cmd != NULL)
return luaL_execresult(L, stat);
else {
lua_pushboolean(L, stat); /* true if there is a shell */
return 1;
}
}
static int os_remove (lua_State *L) {
const char *filename = luaL_checkstring(L, 1);
return luaL_fileresult(L, remove(filename) == 0, filename);
}
static int os_rename (lua_State *L) {
const char *fromname = luaL_checkstring(L, 1);
const char *toname = luaL_checkstring(L, 2);
return luaL_fileresult(L, rename(fromname, toname) == 0, NULL);
}
static int os_tmpname (lua_State *L) {
char buff[LUA_TMPNAMBUFSIZE];
int err;
lua_tmpnam(buff, err);
if (err)
return luaL_error(L, "unable to generate a unique filename");
lua_pushstring(L, buff);
return 1;
}
static int os_getenv (lua_State *L) {
lua_pushstring(L, getenv(luaL_checkstring(L, 1))); /* if NULL push nil */
return 1;
}
static int os_clock (lua_State *L) {
lua_pushnumber(L, ((lua_Number)clock())/(lua_Number)CLOCKS_PER_SEC);
return 1;
}
/*
** {======================================================
** Time/Date operations
** { year=%Y, month=%m, day=%d, hour=%H, min=%M, sec=%S,
** wday=%w+1, yday=%j, isdst=? }
** =======================================================
*/
static void setfield (lua_State *L, const char *key, int value) {
lua_pushinteger(L, value);
lua_setfield(L, -2, key);
}
static void setboolfield (lua_State *L, const char *key, int value) {
if (value < 0) /* undefined? */
return; /* does not set field */
lua_pushboolean(L, value);
lua_setfield(L, -2, key);
}
/*
** Set all fields from structure 'tm' in the table on top of the stack
*/
static void setallfields (lua_State *L, struct tm *stm) {
setfield(L, "sec", stm->tm_sec);
setfield(L, "min", stm->tm_min);
setfield(L, "hour", stm->tm_hour);
setfield(L, "day", stm->tm_mday);
setfield(L, "month", stm->tm_mon + 1);
setfield(L, "year", stm->tm_year + 1900);
setfield(L, "wday", stm->tm_wday + 1);
setfield(L, "yday", stm->tm_yday + 1);
setboolfield(L, "isdst", stm->tm_isdst);
}
static int getboolfield (lua_State *L, const char *key) {
int res;
res = (lua_getfield(L, -1, key) == LUA_TNIL) ? -1 : lua_toboolean(L, -1);
lua_pop(L, 1);
return res;
}
/* maximum value for date fields (to avoid arithmetic overflows with 'int') */
#if !defined(L_MAXDATEFIELD)
#define L_MAXDATEFIELD (INT_MAX / 2)
#endif
static int getfield (lua_State *L, const char *key, int d, int delta) {
int isnum;
int t = lua_getfield(L, -1, key); /* get field and its type */
lua_Integer res = lua_tointegerx(L, -1, &isnum);
if (!isnum) { /* field is not an integer? */
if (t != LUA_TNIL) /* some other value? */
return luaL_error(L, "field '%s' is not an integer", key);
else if (d < 0) /* absent field; no default? */
return luaL_error(L, "field '%s' missing in date table", key);
res = d;
}
else {
if (!(-L_MAXDATEFIELD <= res && res <= L_MAXDATEFIELD))
return luaL_error(L, "field '%s' is out-of-bound", key);
res -= delta;
}
lua_pop(L, 1);
return (int)res;
}
static const char *checkoption (lua_State *L, const char *conv, char *buff) {
const char *option;
int oplen = 1;
for (option = LUA_STRFTIMEOPTIONS; *option != '\0'; option += oplen) {
if (*option == '|') /* next block? */
oplen++; /* next length */
else if (memcmp(conv, option, oplen) == 0) { /* match? */
memcpy(buff, conv, oplen); /* copy valid option to buffer */
buff[oplen] = '\0';
return conv + oplen; /* return next item */
}
}
luaL_argerror(L, 1,
lua_pushfstring(L, "invalid conversion specifier '%%%s'", conv));
return conv; /* to avoid warnings */
}
/* maximum size for an individual 'strftime' item */
#define SIZETIMEFMT 250
static int os_date (lua_State *L) {
const char *s = luaL_optstring(L, 1, "%c");
time_t t = luaL_opt(L, l_checktime, 2, time(NULL));
struct tm tmr, *stm;
if (*s == '!') { /* UTC? */
stm = l_gmtime(&t, &tmr);
s++; /* skip '!' */
}
else
stm = l_localtime(&t, &tmr);
if (stm == NULL) /* invalid date? */
luaL_error(L, "time result cannot be represented in this installation");
if (strcmp(s, "*t") == 0) {
lua_createtable(L, 0, 9); /* 9 = number of fields */
setallfields(L, stm);
}
else {
char cc[4]; /* buffer for individual conversion specifiers */
luaL_Buffer b;
cc[0] = '%';
luaL_buffinit(L, &b);
while (*s) {
if (*s != '%') /* not a conversion specifier? */
luaL_addchar(&b, *s++);
else {
size_t reslen;
char *buff = luaL_prepbuffsize(&b, SIZETIMEFMT);
s = checkoption(L, s + 1, cc + 1); /* copy specifier to 'cc' */
reslen = strftime(buff, SIZETIMEFMT, cc, stm);
luaL_addsize(&b, reslen);
}
}
luaL_pushresult(&b);
}
return 1;
}
static int os_time (lua_State *L) {
time_t t;
if (lua_isnoneornil(L, 1)) /* called without args? */
t = time(NULL); /* get current time */
else {
struct tm ts;
luaL_checktype(L, 1, LUA_TTABLE);
lua_settop(L, 1); /* make sure table is at the top */
ts.tm_sec = getfield(L, "sec", 0, 0);
ts.tm_min = getfield(L, "min", 0, 0);
ts.tm_hour = getfield(L, "hour", 12, 0);
ts.tm_mday = getfield(L, "day", -1, 0);
ts.tm_mon = getfield(L, "month", -1, 1);
ts.tm_year = getfield(L, "year", -1, 1900);
ts.tm_isdst = getboolfield(L, "isdst");
t = mktime(&ts);
setallfields(L, &ts); /* update fields with normalized values */
}
if (t != (time_t)(l_timet)t || t == (time_t)(-1))
luaL_error(L, "time result cannot be represented in this installation");
l_pushtime(L, t);
return 1;
}
static int os_difftime (lua_State *L) {
time_t t1 = l_checktime(L, 1);
time_t t2 = l_checktime(L, 2);
lua_pushnumber(L, (lua_Number)difftime(t1, t2));
return 1;
}
/* }====================================================== */
static int os_setlocale (lua_State *L) {
static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY,
LC_NUMERIC, LC_TIME};
static const char *const catnames[] = {"all", "collate", "ctype", "monetary",
"numeric", "time", NULL};
const char *l = luaL_optstring(L, 1, NULL);
int op = luaL_checkoption(L, 2, "all", catnames);
lua_pushstring(L, setlocale(cat[op], l));
return 1;
}
static int os_exit (lua_State *L) {
int status;
if (lua_isboolean(L, 1))
status = (lua_toboolean(L, 1) ? EXIT_SUCCESS : EXIT_FAILURE);
else
status = (int)luaL_optinteger(L, 1, EXIT_SUCCESS);
if (lua_toboolean(L, 2))
lua_close(L);
if (L) exit(status); /* 'if' to avoid warnings for unreachable 'return' */
return 0;
}
static const luaL_Reg syslib[] = {
{"clock", os_clock},
{"date", os_date},
{"difftime", os_difftime},
{"execute", os_execute},
{"exit", os_exit},
{"getenv", os_getenv},
{"remove", os_remove},
{"rename", os_rename},
{"setlocale", os_setlocale},
{"time", os_time},
{"tmpname", os_tmpname},
{NULL, NULL}
};
/* }====================================================== */
LUAMOD_API int luaopen_os (lua_State *L) {
luaL_newlib(L, syslib);
return 1;
}

1652
deps/lua/lparser.c vendored Normal file

File diff suppressed because it is too large Load Diff

133
deps/lua/lparser.h vendored Normal file
View File

@@ -0,0 +1,133 @@
/*
** $Id: lparser.h,v 1.76 2015/12/30 18:16:13 roberto Exp $
** Lua Parser
** See Copyright Notice in lua.h
*/
#ifndef lparser_h
#define lparser_h
#include "llimits.h"
#include "lobject.h"
#include "lzio.h"
/*
** Expression and variable descriptor.
** Code generation for variables and expressions can be delayed to allow
** optimizations; An 'expdesc' structure describes a potentially-delayed
** variable/expression. It has a description of its "main" value plus a
** list of conditional jumps that can also produce its value (generated
** by short-circuit operators 'and'/'or').
*/
/* kinds of variables/expressions */
typedef enum {
VVOID, /* when 'expdesc' describes the last expression a list,
this kind means an empty list (so, no expression) */
VNIL, /* constant nil */
VTRUE, /* constant true */
VFALSE, /* constant false */
VK, /* constant in 'k'; info = index of constant in 'k' */
VKFLT, /* floating constant; nval = numerical float value */
VKINT, /* integer constant; nval = numerical integer value */
VNONRELOC, /* expression has its value in a fixed register;
info = result register */
VLOCAL, /* local variable; info = local register */
VUPVAL, /* upvalue variable; info = index of upvalue in 'upvalues' */
VINDEXED, /* indexed variable;
ind.vt = whether 't' is register or upvalue;
ind.t = table register or upvalue;
ind.idx = key's R/K index */
VJMP, /* expression is a test/comparison;
info = pc of corresponding jump instruction */
VRELOCABLE, /* expression can put result in any register;
info = instruction pc */
VCALL, /* expression is a function call; info = instruction pc */
VVARARG /* vararg expression; info = instruction pc */
} expkind;
#define vkisvar(k) (VLOCAL <= (k) && (k) <= VINDEXED)
#define vkisinreg(k) ((k) == VNONRELOC || (k) == VLOCAL)
typedef struct expdesc {
expkind k;
union {
lua_Integer ival; /* for VKINT */
lua_Number nval; /* for VKFLT */
int info; /* for generic use */
struct { /* for indexed variables (VINDEXED) */
short idx; /* index (R/K) */
lu_byte t; /* table (register or upvalue) */
lu_byte vt; /* whether 't' is register (VLOCAL) or upvalue (VUPVAL) */
} ind;
} u;
int t; /* patch list of 'exit when true' */
int f; /* patch list of 'exit when false' */
} expdesc;
/* description of active local variable */
typedef struct Vardesc {
short idx; /* variable index in stack */
} Vardesc;
/* description of pending goto statements and label statements */
typedef struct Labeldesc {
TString *name; /* label identifier */
int pc; /* position in code */
int line; /* line where it appeared */
lu_byte nactvar; /* local level where it appears in current block */
} Labeldesc;
/* list of labels or gotos */
typedef struct Labellist {
Labeldesc *arr; /* array */
int n; /* number of entries in use */
int size; /* array size */
} Labellist;
/* dynamic structures used by the parser */
typedef struct Dyndata {
struct { /* list of active local variables */
Vardesc *arr;
int n;
int size;
} actvar;
Labellist gt; /* list of pending gotos */
Labellist label; /* list of active labels */
} Dyndata;
/* control of blocks */
struct BlockCnt; /* defined in lparser.c */
/* state needed to generate code for a given function */
typedef struct FuncState {
Proto *f; /* current function header */
struct FuncState *prev; /* enclosing function */
struct LexState *ls; /* lexical state */
struct BlockCnt *bl; /* chain of current blocks */
int pc; /* next position to code (equivalent to 'ncode') */
int lasttarget; /* 'label' of last 'jump label' */
int jpc; /* list of pending jumps to 'pc' */
int nk; /* number of elements in 'k' */
int np; /* number of elements in 'p' */
int firstlocal; /* index of first local var (in Dyndata array) */
short nlocvars; /* number of elements in 'f->locvars' */
lu_byte nactvar; /* number of active local variables */
lu_byte nups; /* number of upvalues */
lu_byte freereg; /* first free register */
} FuncState;
LUAI_FUNC LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
Dyndata *dyd, const char *name, int firstchar);
#endif

45
deps/lua/lprefix.h vendored Normal file
View File

@@ -0,0 +1,45 @@
/*
** $Id: lprefix.h,v 1.2 2014/12/29 16:54:13 roberto Exp $
** Definitions for Lua code that must come before any other header file
** See Copyright Notice in lua.h
*/
#ifndef lprefix_h
#define lprefix_h
/*
** Allows POSIX/XSI stuff
*/
#if !defined(LUA_USE_C89) /* { */
#if !defined(_XOPEN_SOURCE)
#define _XOPEN_SOURCE 600
#elif _XOPEN_SOURCE == 0
#undef _XOPEN_SOURCE /* use -D_XOPEN_SOURCE=0 to undefine it */
#endif
/*
** Allows manipulation of large files in gcc and some other compilers
*/
#if !defined(LUA_32BITS) && !defined(_FILE_OFFSET_BITS)
#define _LARGEFILE_SOURCE 1
#define _FILE_OFFSET_BITS 64
#endif
#endif /* } */
/*
** Windows stuff
*/
#if defined(_WIN32) /* { */
#if !defined(_CRT_SECURE_NO_WARNINGS)
#define _CRT_SECURE_NO_WARNINGS /* avoid warnings about ISO C functions */
#endif
#endif /* } */
#endif

Some files were not shown because too many files have changed in this diff Show More