mirror of
https://github.com/thewesker/bug-em.git
synced 2025-12-22 04:51:05 -05:00
lol
This commit is contained in:
1
node_modules/ctype/.npmignore
generated
vendored
Normal file
1
node_modules/ctype/.npmignore
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
tst/
|
||||
78
node_modules/ctype/CHANGELOG
generated
vendored
Normal file
78
node_modules/ctype/CHANGELOG
generated
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
This contains tickets fixed in each version release in reverse chronological
|
||||
order. There is one ticket per line. Each commits message has the tickets fixed
|
||||
in it. The commit message also has the corresponding github issue. i.e. CTYPE-42
|
||||
would be issue 42. Each issue can be found at:
|
||||
https://github.com/rmustacc/node-ctype/issues/%d.
|
||||
|
||||
v0.5.3
|
||||
CTYPE-50 Release 0.5.3
|
||||
Contributed by Nick Schonning:
|
||||
CTYPE-49 Add repository section to package.json
|
||||
Contributed by Jonathan Ong:
|
||||
CTYPE-48 Create .npmignore
|
||||
|
||||
v0.5.2
|
||||
CTYPE-46 Release 0.5.2
|
||||
CTYPE-45 error in setEndian logic
|
||||
|
||||
v0.5.1
|
||||
CTYPE-44 Release 0.5.1
|
||||
Contributed by Terin Stock:
|
||||
CTYPE-41 CTypeParser.writeStruct should return its offset
|
||||
Contributed by Terin Stock:
|
||||
CTYPE-42 int64_t returns wrong size
|
||||
|
||||
v0.5.0
|
||||
CTYPE-40 Release 0.5.0
|
||||
CTYPE-39 want > 0.6 engine support
|
||||
|
||||
v0.4.0
|
||||
CTYPE-37 Release v0.4.0
|
||||
CTYPE-6 want additional entry point for write
|
||||
CTYPE-20 Add 64-bit int support into core parser
|
||||
CTYPE-31 Fix bounds errors node/2129
|
||||
CTYPE-33 Update copyright holders
|
||||
CTYPE-34 ctf.js confuses sign bit.
|
||||
CTYPE-35 Make the README more useful for getting started
|
||||
CTYPE-36 want manual page on ctio functions
|
||||
|
||||
v0.3.1
|
||||
CTYPE-29 Release 0.3.1
|
||||
CTYPE-28 Want v0.6 npm support
|
||||
|
||||
v0.3.0
|
||||
CTYPE-27 Release v0.3.0
|
||||
CTYPE-26 Want alternate default char behavior
|
||||
|
||||
v0.2.1
|
||||
CTYPE-25 Release v0.2.1
|
||||
CTYPE-24 Writing structs is busted
|
||||
|
||||
v0.2.0:
|
||||
CTYPE-23 Release v0.2.0
|
||||
CTYPE-21 Add support for CTF JSON data
|
||||
CTYPE-22 Add Javascriptlint profile
|
||||
CTYPE-15 Pull in ctio updates from node/master
|
||||
|
||||
v0.1.0:
|
||||
CTYPE-18 Bump version to v0.1.0
|
||||
CTYPE-17 Fix nested structures
|
||||
CTYPE-16 Remove extraneous logging
|
||||
CTYPE-14 toAbs64 and toApprox64 are not exported
|
||||
|
||||
v0.0.3:
|
||||
CTYPE-12 Bump version to v0.0.3
|
||||
CTYPE-11 fix typo in wuint64
|
||||
CTYPE-10 Integrate jsstyle
|
||||
|
||||
v0.0.2:
|
||||
CTYPE-8 dump npm version to v0.0.2
|
||||
CTYPE-9 want changelog
|
||||
CTYPE-7 fix typo in detypes.
|
||||
|
||||
v0.0.1:
|
||||
CTYPE-5 Missing from NPM registry
|
||||
CTYPE-4 int16_t calls wrong read function
|
||||
CTYPE-3 API example types are missing quotes as strings
|
||||
CTYPE-2 doc missing 64-bit functions
|
||||
CTYPE-1 Need license
|
||||
24
node_modules/ctype/LICENSE
generated
vendored
Normal file
24
node_modules/ctype/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
The following license applies to all files unless the file is specified below.
|
||||
Each file specified below has its license information embedded in it:
|
||||
|
||||
tools/jsstyle
|
||||
|
||||
Copyright 2011, Robert Mustacchi. All rights reserved.
|
||||
Copyright 2011, Joyent, Inc. All rights reserved.
|
||||
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.
|
||||
82
node_modules/ctype/README
generated
vendored
Normal file
82
node_modules/ctype/README
generated
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
Node-CType is a way to read and write binary data in structured and easy to use
|
||||
format. Its name comes from the C header file.
|
||||
|
||||
To get started, simply clone the repository or use npm to install it. Once it is
|
||||
there, simply require it.
|
||||
|
||||
git clone git://github.com/rmustacc/node-ctype
|
||||
npm install ctype
|
||||
var mod_ctype = require('ctype')
|
||||
|
||||
|
||||
There are two APIs that you can use, depending on what abstraction you'd like.
|
||||
The low level API let's you read and write individual integers and floats from
|
||||
buffers. The higher level API let's you read and write structures of these. To
|
||||
illustrate this, let's looks look at how we would read and write a binary
|
||||
encoded x,y point.
|
||||
|
||||
In C we would define this structure as follows:
|
||||
|
||||
typedef struct point {
|
||||
uint16_t p_x;
|
||||
uint16_t p_y;
|
||||
} point_t;
|
||||
|
||||
To read a binary encoded point from a Buffer, we first need to create a CType
|
||||
parser (where we specify the endian and other options) and add the typedef.
|
||||
|
||||
var parser = new mod_ctype.Parser({ endian: 'big' });
|
||||
parser.typedef('point_t', [
|
||||
{ x: { type: 'uint16_t' } },
|
||||
{ y: { type: 'uint16_t' } }
|
||||
]);
|
||||
|
||||
From here, given a buffer buf and an offset into it, we can read a point.
|
||||
|
||||
var out = parser.readData([ { point: { type: 'point_t' } } ], buffer, 0);
|
||||
console.log(out);
|
||||
{ point: { x: 23, y: 42 } }
|
||||
|
||||
Another way to get the same information would be to use the low level methods.
|
||||
Note that these require you to manually deal with the offset. Here's how we'd
|
||||
get the same values of x and y from the buffer.
|
||||
|
||||
var x = mod_ctype.ruint16(buf, 'big', 0);
|
||||
var y = mod_ctype.ruint16(buf, 'big', 2);
|
||||
console.log(x + ', ' + y);
|
||||
23, 42
|
||||
|
||||
The true power of this API comes from the ability to define and nest typedefs,
|
||||
just as you would in C. By default, the following types are defined by default.
|
||||
Note that they return a Number, unless indicated otherwise.
|
||||
|
||||
* int8_t
|
||||
* int16_t
|
||||
* int32_t
|
||||
* int64_t (returns an array where val[0] << 32 + val[1] would be the value)
|
||||
* uint8_t
|
||||
* uint16_t
|
||||
* uint32_t
|
||||
* uint64_t (returns an array where val[0] << 32 + val[1] would be the value)
|
||||
* float
|
||||
* double
|
||||
* char (either returns a buffer with that character or a uint8_t)
|
||||
* char[] (returns an object with the buffer and the number of characters read which is either the total amount requested or until the first 0)
|
||||
|
||||
|
||||
ctf2json integration:
|
||||
|
||||
Node-CType supports consuming the output of ctf2json. Once you read in a JSON file,
|
||||
all you have to do to add all the definitions it contains is:
|
||||
|
||||
var data, parser;
|
||||
data = JSON.parse(parsedJSONData);
|
||||
parser = mod_ctype.parseCTF(data, { endian: 'big' });
|
||||
|
||||
For more documentation, see the file README.old. Full documentation is in the
|
||||
process of being rewritten as a series of manual pages which will be available
|
||||
in the repository and online for viewing.
|
||||
|
||||
To read the ctio manual page simple run, from the root of the workspace:
|
||||
|
||||
man -Mman -s 3ctype ctio
|
||||
298
node_modules/ctype/README.old
generated
vendored
Normal file
298
node_modules/ctype/README.old
generated
vendored
Normal file
@@ -0,0 +1,298 @@
|
||||
This library provides a way to read and write binary data.
|
||||
|
||||
Node CType is a way to read and write binary data in structured and easy to use
|
||||
formats. It's name comes from the header file, though it does not share as much
|
||||
with it as it perhaps should.
|
||||
|
||||
There are two levels of the API. One is the raw API which everything is built on
|
||||
top of, while the other provides a much nicer abstraction and is built entirely
|
||||
by using the lower level API. The hope is that the low level API is both clear
|
||||
and useful. The low level API gets it's names from stdint.h (a rather
|
||||
appropriate source). The lower level API is presented at the end of this
|
||||
document.
|
||||
|
||||
Standard CType API
|
||||
|
||||
The CType interface is presented as a parser object that controls the
|
||||
endianness combined with a series of methods to change that value, parse and
|
||||
write out buffers, and a way to provide typedefs. Standard Types
|
||||
|
||||
The CType parser supports the following basic types which return Numbers except
|
||||
as indicated:
|
||||
|
||||
* int8_t
|
||||
* int16_t
|
||||
* int32_t
|
||||
* int64_t (returns an array where val[0] << 32 + val[1] would be the value)
|
||||
* uint8_t
|
||||
* uint16_t
|
||||
* uint32_t
|
||||
* uint64_t (returns an array where val[0] << 32 + val[1] would be the value)
|
||||
* float
|
||||
* double
|
||||
* char (returns a buffer with just that single character)
|
||||
* char[] (returns an object with the buffer and the number of characters read which is either the total amount requested or until the first 0)
|
||||
|
||||
Specifying Structs
|
||||
|
||||
The CType parser also supports the notion of structs. A struct is an array of
|
||||
JSON objects that defines an order of keys which have types and values. One
|
||||
would build a struct to represent a point (x,y) as follows:
|
||||
|
||||
[
|
||||
{ x: { type: 'int16_t' }},
|
||||
{ y: { type: 'int16_t' }}
|
||||
]
|
||||
|
||||
When this is passed into the read routine, it would read the first two bytes
|
||||
(as defined by int16_t) to determine the Number to use for X, and then it would
|
||||
read the next two bytes to determine the value of Y. When read this could
|
||||
return something like:
|
||||
|
||||
{
|
||||
x: 42,
|
||||
y: -23
|
||||
}
|
||||
|
||||
When someone wants to write values, we use the same format as above, but with
|
||||
additional value field:
|
||||
|
||||
[
|
||||
{ x: { type: 'int16_t', value: 42 }},
|
||||
{ y: { type: 'int16_t', value: -23 }}
|
||||
]
|
||||
|
||||
Now, the structure above may be optionally annotated with offsets. This tells
|
||||
us to rather than read continuously we should read the given value at the
|
||||
specified offset. If an offset is provided, it is is effectively the equivalent
|
||||
of lseek(offset, SEEK_SET). Thus, subsequent values will be read from that
|
||||
offset and incremented by the appropriate value. As an example:
|
||||
|
||||
[
|
||||
{ x: { type: 'int16_t' }},
|
||||
{ y: { type: 'int16_t', offset: 20 }},
|
||||
{ z: { type: 'int16_t' }}
|
||||
]
|
||||
|
||||
We would read x from the first starting offset given to us, for the sake of
|
||||
example, let's assume that's 0. After reading x, the next offset to read from
|
||||
would be 2; however, y specifies an offset, thus we jump directly to that
|
||||
offset and read y from byte 20. We would then read z from byte 22.
|
||||
|
||||
The same offsets may be used when writing values.
|
||||
|
||||
Typedef
|
||||
|
||||
The basic set of types while covers the basics, is somewhat limiting. To make
|
||||
this richer, there is functionality to typedef something like in C. One can use
|
||||
typedef to add a new name to an existing type or to define a name to refer to a
|
||||
struct. Thus the following are all examples of a typedef:
|
||||
|
||||
typedef('size_t', 'uint32_t');
|
||||
typedef('ssize_t', 'int32_t');
|
||||
typedef('point_t', [
|
||||
{ x: { type: 'int16_t' }},
|
||||
{ y: { type: 'int16_t' }}
|
||||
]);
|
||||
|
||||
Once something has been typedef'd it can be used in any of the definitions
|
||||
previously shown.
|
||||
|
||||
One cannot remove a typedef once created, this is analogous to C.
|
||||
|
||||
The set of defined types can be printed with lstypes. The format of this output
|
||||
is subject to change, but likely will look something like:
|
||||
|
||||
> lstypes();
|
||||
{
|
||||
size_t: 'uint32_t',
|
||||
ssize_t: 'int32_t',
|
||||
point_t: [
|
||||
{ x: { type: 'int16_t' }},
|
||||
{ y: { type: 'int16_t' }}
|
||||
]
|
||||
}
|
||||
|
||||
Specifying arrays
|
||||
|
||||
Arrays can be specified by appending []s to a type. Arrays must have the size
|
||||
specified. The size must be specified and it can be done in one of two ways:
|
||||
|
||||
* An explicit non-zero integer size
|
||||
* A name of a previously declared variable in the struct whose value is a
|
||||
number.
|
||||
|
||||
Note, that when using the name of a variable, it should be the string name for
|
||||
the key. This is only valid inside structs and the value must be declared
|
||||
before the value with the array. The following are examples:
|
||||
|
||||
[
|
||||
{ ip_addr4: { type: 'uint8_t[4]' }},
|
||||
{ len: { type: 'uint32_t' }},
|
||||
{ data: { type: 'uint8_t[len]' }}
|
||||
]
|
||||
|
||||
Arrays are permitted in typedefs; however, they must have a declared integer
|
||||
size. The following are examples of valid and invalid arrays:
|
||||
|
||||
typedef('path', 'char[1024]'); /* Good */
|
||||
typedef('path', 'char[len]'); /* Bad! */
|
||||
|
||||
64 bit values:
|
||||
|
||||
Unfortunately Javascript represents values with a double, so you lose precision
|
||||
and the ability to represent Integers roughly beyond 2^53. To alleviate this, I
|
||||
propose the following for returning 64 bit integers when read:
|
||||
|
||||
value[2]: Each entry is a 32 bit number which can be reconstructed to the
|
||||
original by the following formula:
|
||||
|
||||
value[0] << 32 + value[1] (Note this will not work in Javascript)
|
||||
|
||||
CTF JSON data:
|
||||
|
||||
node-ctype can also handle JSON data that mathces the format described in the
|
||||
documentation of the tool ctf2json. Given the JSON data which specifies type
|
||||
information, it will transform that into a parser that understands all of the
|
||||
types defined inside of it. This is useful for more complicated structures that
|
||||
have a lot of typedefs.
|
||||
|
||||
Interface overview
|
||||
|
||||
The following is the header-file like interface to the parser object:
|
||||
|
||||
/*
|
||||
* Create a new instance of the parser. Each parser has its own store of
|
||||
* typedefs and endianness. Conf is an object with the following values:
|
||||
*
|
||||
* endian Either 'big' or 'little' do determine the endianness we
|
||||
* want to read from or write to.
|
||||
*
|
||||
*/
|
||||
function CTypeParser(conf);
|
||||
|
||||
/*
|
||||
* Parses the CTF JSON data and creates a parser that understands all of those
|
||||
* types.
|
||||
*
|
||||
* data Parsed JSON data that maches that CTF JSON
|
||||
* specification.
|
||||
*
|
||||
* conf The configuration object to create a new CTypeParser
|
||||
* from.
|
||||
*/
|
||||
CTypeParser parseCTF(data, conf);
|
||||
|
||||
/*
|
||||
* This is what we were born to do. We read the data from a buffer and return it
|
||||
* in an object whose keys match the values from the object.
|
||||
*
|
||||
* def The array definition of the data to read in
|
||||
*
|
||||
* buffer The buffer to read data from
|
||||
*
|
||||
* offset The offset to start writing to
|
||||
*
|
||||
* Returns an object where each key corresponds to an entry in def and the value
|
||||
* is the read value.
|
||||
*/
|
||||
Object CTypeParser.readData(<Type Definition>, buffer, offset);
|
||||
|
||||
/*
|
||||
* This is the second half of what we were born to do, write out the data
|
||||
* itself.
|
||||
*
|
||||
* def The array definition of the data to write out with
|
||||
* values
|
||||
*
|
||||
* buffer The buffer to write to
|
||||
*
|
||||
* offset The offset in the buffer to write to
|
||||
*/
|
||||
void CTypeParser.writeData(<Type Definition>, buffer, offset);
|
||||
|
||||
/*
|
||||
* A user has requested to add a type, let us honor their request. Yet, if their
|
||||
* request doth spurn us, send them unto the Hells which Dante describes.
|
||||
*
|
||||
* name The string for the type definition we're adding
|
||||
*
|
||||
* value Either a string that is a type/array name or an object
|
||||
* that describes a struct.
|
||||
*/
|
||||
void CTypeParser.prototype.typedef(name, value);
|
||||
|
||||
Object CTypeParser.prototype.lstypes();
|
||||
|
||||
/*
|
||||
* Get the endian value for the current parser
|
||||
*/
|
||||
String CTypeParser.prototype.getEndian();
|
||||
|
||||
/*
|
||||
* Sets the current endian value for the Parser. If the value is not valid,
|
||||
* throws an Error.
|
||||
*
|
||||
* endian Either 'big' or 'little' do determine the endianness we
|
||||
* want to read from or write to.
|
||||
*
|
||||
*/
|
||||
void CTypeParser.protoype.setEndian(String);
|
||||
|
||||
/*
|
||||
* Attempts to convert an array of two integers returned from rsint64 / ruint64
|
||||
* into an absolute 64 bit number. If however the value would exceed 2^52 this
|
||||
* will instead throw an error. The mantissa in a double is a 52 bit number and
|
||||
* rather than potentially give you a value that is an approximation this will
|
||||
* error. If you would rather an approximation, please see toApprox64.
|
||||
*
|
||||
* val An array of two 32-bit integers
|
||||
*/
|
||||
Number function toAbs64(val)
|
||||
|
||||
/*
|
||||
* Will return the 64 bit value as returned in an array from rsint64 / ruint64
|
||||
* to a value as close as it can. Note that Javascript stores all numbers as a
|
||||
* double and the mantissa only has 52 bits. Thus this version may approximate
|
||||
* the value.
|
||||
*
|
||||
* val An array of two 32-bit integers
|
||||
*/
|
||||
Number function toApprox64(val)
|
||||
|
||||
Low Level API
|
||||
|
||||
The following function are provided at the low level:
|
||||
|
||||
Read unsigned integers from a buffer:
|
||||
Number ruint8(buffer, endian, offset);
|
||||
Number ruint16(buffer, endian, offset);
|
||||
Number ruint32(buffer, endian, offset);
|
||||
Number[] ruint64(buffer, endian, offset);
|
||||
|
||||
Read signed integers from a buffer:
|
||||
Number rsint8(buffer, endian, offset);
|
||||
Number rsint16(buffer, endian, offset);
|
||||
Number rsint32(buffer, endian, offset);
|
||||
Number[] rsint64(buffer, endian, offset);
|
||||
|
||||
Read floating point numbers from a buffer:
|
||||
Number rfloat(buffer, endian, offset); /* IEEE-754 Single precision */
|
||||
Number rdouble(buffer, endian, offset); /* IEEE-754 Double precision */
|
||||
|
||||
Write unsigned integers to a buffer:
|
||||
void wuint8(Number, endian, buffer, offset);
|
||||
void wuint16(Number, endian, buffer, offset);
|
||||
void wuint32(Number, endian, buffer, offset);
|
||||
void wuint64(Number[], endian, buffer, offset);
|
||||
|
||||
Write signed integers from a buffer:
|
||||
void wsint8(Number, endian, buffer, offset);
|
||||
void wsint16(Number, endian, buffer, offset);
|
||||
void wsint32(Number, endian, buffer, offset);
|
||||
void wsint64(Number[], endian, buffer offset);
|
||||
|
||||
Write floating point numbers from a buffer:
|
||||
void wfloat(Number, buffer, endian, offset); /* IEEE-754 Single precision */
|
||||
void wdouble(Number, buffer, endian, offset); /* IEEE-754 Double precision */
|
||||
|
||||
245
node_modules/ctype/ctf.js
generated
vendored
Normal file
245
node_modules/ctype/ctf.js
generated
vendored
Normal file
@@ -0,0 +1,245 @@
|
||||
/*
|
||||
* ctf.js
|
||||
*
|
||||
* Understand and parse all of the different JSON formats of CTF data and
|
||||
* translate that into a series of node-ctype friendly pieces. The reason for
|
||||
* the abstraction is to handle different changes in the file format.
|
||||
*
|
||||
* We have to be careful here that we don't end up using a name that is already
|
||||
* a built in type.
|
||||
*/
|
||||
var mod_assert = require('assert');
|
||||
var ASSERT = mod_assert.ok;
|
||||
|
||||
var ctf_versions = [ '1.0' ];
|
||||
var ctf_entries = [ 'integer', 'float', 'typedef', 'struct' ];
|
||||
var ctf_deftypes = [ 'int8_t', 'uint8_t', 'int16_t', 'uint16_t', 'int32_t',
|
||||
'uint32_t', 'float', 'double' ];
|
||||
|
||||
function ctfParseInteger(entry, ctype)
|
||||
{
|
||||
var name, sign, len, type;
|
||||
|
||||
name = entry['name'];
|
||||
if (!('signed' in entry['integer']))
|
||||
throw (new Error('Malformed CTF JSON: integer missing ' +
|
||||
'signed value'));
|
||||
|
||||
|
||||
if (!('length' in entry['integer']))
|
||||
throw (new Error('Malformed CTF JSON: integer missing ' +
|
||||
'length value'));
|
||||
|
||||
sign = entry['integer']['signed'];
|
||||
len = entry['integer']['length'];
|
||||
type = null;
|
||||
|
||||
if (sign && len == 1)
|
||||
type = 'int8_t';
|
||||
else if (len == 1)
|
||||
type = 'uint8_t';
|
||||
else if (sign && len == 2)
|
||||
type = 'int16_t';
|
||||
else if (len == 2)
|
||||
type = 'uint16_t';
|
||||
else if (sign && len == 4)
|
||||
type = 'int32_t';
|
||||
else if (len == 4)
|
||||
type = 'uint32_t';
|
||||
else if (sign && len == 8)
|
||||
type = 'int64_t';
|
||||
else if (len == 8)
|
||||
type = 'uint64_t';
|
||||
|
||||
if (type === null)
|
||||
throw (new Error('Malformed CTF JSON: integer has ' +
|
||||
'unsupported length and sign - ' + len + '/' + sign));
|
||||
|
||||
/*
|
||||
* This means that this is the same as one of our built in types. If
|
||||
* that's the case defining it would be an error. So instead of trying
|
||||
* to typedef it, we'll return here.
|
||||
*/
|
||||
if (name == type)
|
||||
return;
|
||||
|
||||
if (name == 'char') {
|
||||
ASSERT(type == 'int8_t');
|
||||
return;
|
||||
}
|
||||
|
||||
ctype.typedef(name, type);
|
||||
}
|
||||
|
||||
function ctfParseFloat(entry, ctype)
|
||||
{
|
||||
var name, len;
|
||||
|
||||
name = entry['name'];
|
||||
if (!('length' in entry['float']))
|
||||
throw (new Error('Malformed CTF JSON: float missing ' +
|
||||
'length value'));
|
||||
|
||||
len = entry['float']['length'];
|
||||
if (len != 4 && len != 8)
|
||||
throw (new Error('Malformed CTF JSON: float has invalid ' +
|
||||
'length value'));
|
||||
|
||||
if (len == 4) {
|
||||
if (name == 'float')
|
||||
return;
|
||||
ctype.typedef(name, 'float');
|
||||
} else if (len == 8) {
|
||||
if (name == 'double')
|
||||
return;
|
||||
ctype.typedef(name, 'double');
|
||||
}
|
||||
}
|
||||
|
||||
function ctfParseTypedef(entry, ctype)
|
||||
{
|
||||
var name, type, ii;
|
||||
|
||||
name = entry['name'];
|
||||
if (typeof (entry['typedef']) != 'string')
|
||||
throw (new Error('Malformed CTF JSON: typedef value in not ' +
|
||||
'a string'));
|
||||
|
||||
type = entry['typedef'];
|
||||
|
||||
/*
|
||||
* We need to ensure that we're not looking at type that's one of our
|
||||
* built in types. Traditionally in C a uint32_t would be a typedef to
|
||||
* some kind of integer. However, those size types are built ins.
|
||||
*/
|
||||
for (ii = 0; ii < ctf_deftypes.length; ii++) {
|
||||
if (name == ctf_deftypes[ii])
|
||||
return;
|
||||
}
|
||||
|
||||
ctype.typedef(name, type);
|
||||
}
|
||||
|
||||
function ctfParseStruct(entry, ctype)
|
||||
{
|
||||
var name, type, ii, val, index, member, push;
|
||||
|
||||
member = [];
|
||||
if (!Array.isArray(entry['struct']))
|
||||
throw (new Error('Malformed CTF JSON: struct value is not ' +
|
||||
'an array'));
|
||||
|
||||
for (ii = 0; ii < entry['struct'].length; ii++) {
|
||||
val = entry['struct'][ii];
|
||||
if (!('name' in val))
|
||||
throw (new Error('Malformed CTF JSON: struct member ' +
|
||||
'missing name'));
|
||||
|
||||
if (!('type' in val))
|
||||
throw (new Error('Malformed CTF JSON: struct member ' +
|
||||
'missing type'));
|
||||
|
||||
if (typeof (val['name']) != 'string')
|
||||
throw (new Error('Malformed CTF JSON: struct member ' +
|
||||
'name isn\'t a string'));
|
||||
|
||||
if (typeof (val['type']) != 'string')
|
||||
throw (new Error('Malformed CTF JSON: struct member ' +
|
||||
'type isn\'t a string'));
|
||||
|
||||
/*
|
||||
* CTF version 2 specifies array names as <type> [<num>] where
|
||||
* as node-ctype does this as <type>[<num>].
|
||||
*/
|
||||
name = val['name'];
|
||||
type = val['type'];
|
||||
index = type.indexOf(' [');
|
||||
if (index != -1) {
|
||||
type = type.substring(0, index) +
|
||||
type.substring(index + 1, type.length);
|
||||
}
|
||||
push = {};
|
||||
push[name] = { 'type': type };
|
||||
member.push(push);
|
||||
}
|
||||
|
||||
name = entry['name'];
|
||||
ctype.typedef(name, member);
|
||||
}
|
||||
|
||||
function ctfParseEntry(entry, ctype)
|
||||
{
|
||||
var ii, found;
|
||||
|
||||
if (!('name' in entry))
|
||||
throw (new Error('Malformed CTF JSON: entry missing "name" ' +
|
||||
'section'));
|
||||
|
||||
for (ii = 0; ii < ctf_entries.length; ii++) {
|
||||
if (ctf_entries[ii] in entry)
|
||||
found++;
|
||||
}
|
||||
|
||||
if (found === 0)
|
||||
throw (new Error('Malformed CTF JSON: found no entries'));
|
||||
|
||||
if (found >= 2)
|
||||
throw (new Error('Malformed CTF JSON: found more than one ' +
|
||||
'entry'));
|
||||
|
||||
if ('integer' in entry) {
|
||||
ctfParseInteger(entry, ctype);
|
||||
return;
|
||||
}
|
||||
|
||||
if ('float' in entry) {
|
||||
ctfParseFloat(entry, ctype);
|
||||
return;
|
||||
}
|
||||
|
||||
if ('typedef' in entry) {
|
||||
ctfParseTypedef(entry, ctype);
|
||||
return;
|
||||
}
|
||||
|
||||
if ('struct' in entry) {
|
||||
ctfParseStruct(entry, ctype);
|
||||
return;
|
||||
}
|
||||
|
||||
ASSERT(false, 'shouldn\'t reach here');
|
||||
}
|
||||
|
||||
function ctfParseJson(json, ctype)
|
||||
{
|
||||
var version, ii;
|
||||
|
||||
ASSERT(json);
|
||||
ASSERT(ctype);
|
||||
if (!('metadata' in json))
|
||||
throw (new Error('Invalid CTF JSON: missing metadata section'));
|
||||
|
||||
if (!('ctf2json_version' in json['metadata']))
|
||||
throw (new Error('Invalid CTF JSON: missing ctf2json_version'));
|
||||
|
||||
version = json['metadata']['ctf2json_version'];
|
||||
for (ii = 0; ii < ctf_versions.length; ii++) {
|
||||
if (ctf_versions[ii] == version)
|
||||
break;
|
||||
}
|
||||
|
||||
if (ii == ctf_versions.length)
|
||||
throw (new Error('Unsuported ctf2json_version: ' + version));
|
||||
|
||||
if (!('data' in json))
|
||||
throw (new Error('Invalid CTF JSON: missing data section'));
|
||||
|
||||
if (!Array.isArray(json['data']))
|
||||
throw (new Error('Malformed CTF JSON: data section is not ' +
|
||||
'an array'));
|
||||
|
||||
for (ii = 0; ii < json['data'].length; ii++)
|
||||
ctfParseEntry(json['data'][ii], ctype);
|
||||
}
|
||||
|
||||
exports.ctfParseJson = ctfParseJson;
|
||||
1485
node_modules/ctype/ctio.js
generated
vendored
Normal file
1485
node_modules/ctype/ctio.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
944
node_modules/ctype/ctype.js
generated
vendored
Normal file
944
node_modules/ctype/ctype.js
generated
vendored
Normal file
@@ -0,0 +1,944 @@
|
||||
/*
|
||||
* rm - Feb 2011
|
||||
* ctype.js
|
||||
*
|
||||
* This module provides a simple abstraction towards reading and writing
|
||||
* different types of binary data. It is designed to use ctio.js and provide a
|
||||
* richer and more expressive API on top of it.
|
||||
*
|
||||
* By default we support the following as built in basic types:
|
||||
* int8_t
|
||||
* int16_t
|
||||
* int32_t
|
||||
* uint8_t
|
||||
* uint16_t
|
||||
* uint32_t
|
||||
* uint64_t
|
||||
* float
|
||||
* double
|
||||
* char
|
||||
* char[]
|
||||
*
|
||||
* Each type is returned as a Number, with the exception of char and char[]
|
||||
* which are returned as Node Buffers. A char is considered a uint8_t.
|
||||
*
|
||||
* Requests to read and write data are specified as an array of JSON objects.
|
||||
* This is also the same way that one declares structs. Even if just a single
|
||||
* value is requested, it must be done as a struct. The array order determines
|
||||
* the order that we try and read values. Each entry has the following format
|
||||
* with values marked with a * being optional.
|
||||
*
|
||||
* { key: { type: /type/, value*: /value/, offset*: /offset/ }
|
||||
*
|
||||
* If offset is defined, we lseek(offset, SEEK_SET) before reading the next
|
||||
* value. Value is defined when we're writing out data, otherwise it's ignored.
|
||||
*
|
||||
*/
|
||||
|
||||
var mod_ctf = require('./ctf.js');
|
||||
var mod_ctio = require('./ctio.js');
|
||||
var mod_assert = require('assert');
|
||||
|
||||
/*
|
||||
* This is the set of basic types that we support.
|
||||
*
|
||||
* read The function to call to read in a value from a buffer
|
||||
*
|
||||
* write The function to call to write a value to a buffer
|
||||
*
|
||||
*/
|
||||
var deftypes = {
|
||||
'uint8_t': { read: ctReadUint8, write: ctWriteUint8 },
|
||||
'uint16_t': { read: ctReadUint16, write: ctWriteUint16 },
|
||||
'uint32_t': { read: ctReadUint32, write: ctWriteUint32 },
|
||||
'uint64_t': { read: ctReadUint64, write: ctWriteUint64 },
|
||||
'int8_t': { read: ctReadSint8, write: ctWriteSint8 },
|
||||
'int16_t': { read: ctReadSint16, write: ctWriteSint16 },
|
||||
'int32_t': { read: ctReadSint32, write: ctWriteSint32 },
|
||||
'int64_t': { read: ctReadSint64, write: ctWriteSint64 },
|
||||
'float': { read: ctReadFloat, write: ctWriteFloat },
|
||||
'double': { read: ctReadDouble, write: ctWriteDouble },
|
||||
'char': { read: ctReadChar, write: ctWriteChar },
|
||||
'char[]': { read: ctReadCharArray, write: ctWriteCharArray }
|
||||
};
|
||||
|
||||
/*
|
||||
* The following are wrappers around the CType IO low level API. They encode
|
||||
* knowledge about the size and return something in the expected format.
|
||||
*/
|
||||
function ctReadUint8(endian, buffer, offset)
|
||||
{
|
||||
var val = mod_ctio.ruint8(buffer, endian, offset);
|
||||
return ({ value: val, size: 1 });
|
||||
}
|
||||
|
||||
function ctReadUint16(endian, buffer, offset)
|
||||
{
|
||||
var val = mod_ctio.ruint16(buffer, endian, offset);
|
||||
return ({ value: val, size: 2 });
|
||||
}
|
||||
|
||||
function ctReadUint32(endian, buffer, offset)
|
||||
{
|
||||
var val = mod_ctio.ruint32(buffer, endian, offset);
|
||||
return ({ value: val, size: 4 });
|
||||
}
|
||||
|
||||
function ctReadUint64(endian, buffer, offset)
|
||||
{
|
||||
var val = mod_ctio.ruint64(buffer, endian, offset);
|
||||
return ({ value: val, size: 8 });
|
||||
}
|
||||
|
||||
function ctReadSint8(endian, buffer, offset)
|
||||
{
|
||||
var val = mod_ctio.rsint8(buffer, endian, offset);
|
||||
return ({ value: val, size: 1 });
|
||||
}
|
||||
|
||||
function ctReadSint16(endian, buffer, offset)
|
||||
{
|
||||
var val = mod_ctio.rsint16(buffer, endian, offset);
|
||||
return ({ value: val, size: 2 });
|
||||
}
|
||||
|
||||
function ctReadSint32(endian, buffer, offset)
|
||||
{
|
||||
var val = mod_ctio.rsint32(buffer, endian, offset);
|
||||
return ({ value: val, size: 4 });
|
||||
}
|
||||
|
||||
function ctReadSint64(endian, buffer, offset)
|
||||
{
|
||||
var val = mod_ctio.rsint64(buffer, endian, offset);
|
||||
return ({ value: val, size: 8 });
|
||||
}
|
||||
|
||||
function ctReadFloat(endian, buffer, offset)
|
||||
{
|
||||
var val = mod_ctio.rfloat(buffer, endian, offset);
|
||||
return ({ value: val, size: 4 });
|
||||
}
|
||||
|
||||
function ctReadDouble(endian, buffer, offset)
|
||||
{
|
||||
var val = mod_ctio.rdouble(buffer, endian, offset);
|
||||
return ({ value: val, size: 8 });
|
||||
}
|
||||
|
||||
/*
|
||||
* Reads a single character into a node buffer
|
||||
*/
|
||||
function ctReadChar(endian, buffer, offset)
|
||||
{
|
||||
var res = new Buffer(1);
|
||||
res[0] = mod_ctio.ruint8(buffer, endian, offset);
|
||||
return ({ value: res, size: 1 });
|
||||
}
|
||||
|
||||
function ctReadCharArray(length, endian, buffer, offset)
|
||||
{
|
||||
var ii;
|
||||
var res = new Buffer(length);
|
||||
|
||||
for (ii = 0; ii < length; ii++)
|
||||
res[ii] = mod_ctio.ruint8(buffer, endian, offset + ii);
|
||||
|
||||
return ({ value: res, size: length });
|
||||
}
|
||||
|
||||
function ctWriteUint8(value, endian, buffer, offset)
|
||||
{
|
||||
mod_ctio.wuint8(value, endian, buffer, offset);
|
||||
return (1);
|
||||
}
|
||||
|
||||
function ctWriteUint16(value, endian, buffer, offset)
|
||||
{
|
||||
mod_ctio.wuint16(value, endian, buffer, offset);
|
||||
return (2);
|
||||
}
|
||||
|
||||
function ctWriteUint32(value, endian, buffer, offset)
|
||||
{
|
||||
mod_ctio.wuint32(value, endian, buffer, offset);
|
||||
return (4);
|
||||
}
|
||||
|
||||
function ctWriteUint64(value, endian, buffer, offset)
|
||||
{
|
||||
mod_ctio.wuint64(value, endian, buffer, offset);
|
||||
return (8);
|
||||
}
|
||||
|
||||
function ctWriteSint8(value, endian, buffer, offset)
|
||||
{
|
||||
mod_ctio.wsint8(value, endian, buffer, offset);
|
||||
return (1);
|
||||
}
|
||||
|
||||
function ctWriteSint16(value, endian, buffer, offset)
|
||||
{
|
||||
mod_ctio.wsint16(value, endian, buffer, offset);
|
||||
return (2);
|
||||
}
|
||||
|
||||
function ctWriteSint32(value, endian, buffer, offset)
|
||||
{
|
||||
mod_ctio.wsint32(value, endian, buffer, offset);
|
||||
return (4);
|
||||
}
|
||||
|
||||
function ctWriteSint64(value, endian, buffer, offset)
|
||||
{
|
||||
mod_ctio.wsint64(value, endian, buffer, offset);
|
||||
return (8);
|
||||
}
|
||||
|
||||
function ctWriteFloat(value, endian, buffer, offset)
|
||||
{
|
||||
mod_ctio.wfloat(value, endian, buffer, offset);
|
||||
return (4);
|
||||
}
|
||||
|
||||
function ctWriteDouble(value, endian, buffer, offset)
|
||||
{
|
||||
mod_ctio.wdouble(value, endian, buffer, offset);
|
||||
return (8);
|
||||
}
|
||||
|
||||
/*
|
||||
* Writes a single character into a node buffer
|
||||
*/
|
||||
function ctWriteChar(value, endian, buffer, offset)
|
||||
{
|
||||
if (!(value instanceof Buffer))
|
||||
throw (new Error('Input must be a buffer'));
|
||||
|
||||
mod_ctio.ruint8(value[0], endian, buffer, offset);
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* We're going to write 0s into the buffer if the string is shorter than the
|
||||
* length of the array.
|
||||
*/
|
||||
function ctWriteCharArray(value, length, endian, buffer, offset)
|
||||
{
|
||||
var ii;
|
||||
|
||||
if (!(value instanceof Buffer))
|
||||
throw (new Error('Input must be a buffer'));
|
||||
|
||||
if (value.length > length)
|
||||
throw (new Error('value length greater than array length'));
|
||||
|
||||
for (ii = 0; ii < value.length && ii < length; ii++)
|
||||
mod_ctio.wuint8(value[ii], endian, buffer, offset + ii);
|
||||
|
||||
for (; ii < length; ii++)
|
||||
mod_ctio.wuint8(0, endian, offset + ii);
|
||||
|
||||
|
||||
return (length);
|
||||
}
|
||||
|
||||
/*
|
||||
* Each parser has their own set of types. We want to make sure that they each
|
||||
* get their own copy as they may need to modify it.
|
||||
*/
|
||||
function ctGetBasicTypes()
|
||||
{
|
||||
var ret = {};
|
||||
var key;
|
||||
for (key in deftypes)
|
||||
ret[key] = deftypes[key];
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a string in the form of type[length] we want to split this into an
|
||||
* object that extracts that information. We want to note that we could possibly
|
||||
* have nested arrays so this should only check the furthest one. It may also be
|
||||
* the case that we have no [] pieces, in which case we just return the current
|
||||
* type.
|
||||
*/
|
||||
function ctParseType(str)
|
||||
{
|
||||
var begInd, endInd;
|
||||
var type, len;
|
||||
if (typeof (str) != 'string')
|
||||
throw (new Error('type must be a Javascript string'));
|
||||
|
||||
endInd = str.lastIndexOf(']');
|
||||
if (endInd == -1) {
|
||||
if (str.lastIndexOf('[') != -1)
|
||||
throw (new Error('found invalid type with \'[\' but ' +
|
||||
'no corresponding \']\''));
|
||||
|
||||
return ({ type: str });
|
||||
}
|
||||
|
||||
begInd = str.lastIndexOf('[');
|
||||
if (begInd == -1)
|
||||
throw (new Error('found invalid type with \']\' but ' +
|
||||
'no corresponding \'[\''));
|
||||
|
||||
if (begInd >= endInd)
|
||||
throw (new Error('malformed type, \']\' appears before \'[\''));
|
||||
|
||||
type = str.substring(0, begInd);
|
||||
len = str.substring(begInd + 1, endInd);
|
||||
|
||||
return ({ type: type, len: len });
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a request validate that all of the fields for it are valid and make
|
||||
* sense. This includes verifying the following notions:
|
||||
* - Each type requested is present in types
|
||||
* - Only allow a name for a field to be specified once
|
||||
* - If an array is specified, validate that the requested field exists and
|
||||
* comes before it.
|
||||
* - If fields is defined, check that each entry has the occurrence of field
|
||||
*/
|
||||
function ctCheckReq(def, types, fields)
|
||||
{
|
||||
var ii, jj;
|
||||
var req, keys, key;
|
||||
var found = {};
|
||||
|
||||
if (!(def instanceof Array))
|
||||
throw (new Error('definition is not an array'));
|
||||
|
||||
if (def.length === 0)
|
||||
throw (new Error('definition must have at least one element'));
|
||||
|
||||
for (ii = 0; ii < def.length; ii++) {
|
||||
req = def[ii];
|
||||
if (!(req instanceof Object))
|
||||
throw (new Error('definition must be an array of' +
|
||||
'objects'));
|
||||
|
||||
keys = Object.keys(req);
|
||||
if (keys.length != 1)
|
||||
throw (new Error('definition entry must only have ' +
|
||||
'one key'));
|
||||
|
||||
if (keys[0] in found)
|
||||
throw (new Error('Specified name already ' +
|
||||
'specified: ' + keys[0]));
|
||||
|
||||
if (!('type' in req[keys[0]]))
|
||||
throw (new Error('missing required type definition'));
|
||||
|
||||
key = ctParseType(req[keys[0]]['type']);
|
||||
|
||||
/*
|
||||
* We may have nested arrays, we need to check the validity of
|
||||
* the types until the len field is undefined in key. However,
|
||||
* each time len is defined we need to verify it is either an
|
||||
* integer or corresponds to an already seen key.
|
||||
*/
|
||||
while (key['len'] !== undefined) {
|
||||
if (isNaN(parseInt(key['len'], 10))) {
|
||||
if (!(key['len'] in found))
|
||||
throw (new Error('Given an array ' +
|
||||
'length without a matching type'));
|
||||
|
||||
}
|
||||
|
||||
key = ctParseType(key['type']);
|
||||
}
|
||||
|
||||
/* Now we can validate if the type is valid */
|
||||
if (!(key['type'] in types))
|
||||
throw (new Error('type not found or typdefed: ' +
|
||||
key['type']));
|
||||
|
||||
/* Check for any required fields */
|
||||
if (fields !== undefined) {
|
||||
for (jj = 0; jj < fields.length; jj++) {
|
||||
if (!(fields[jj] in req[keys[0]]))
|
||||
throw (new Error('Missing required ' +
|
||||
'field: ' + fields[jj]));
|
||||
}
|
||||
}
|
||||
|
||||
found[keys[0]] = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Create a new instance of the parser. Each parser has its own store of
|
||||
* typedefs and endianness. Conf is an object with the following required
|
||||
* values:
|
||||
*
|
||||
* endian Either 'big' or 'little' do determine the endianness we
|
||||
* want to read from or write to.
|
||||
*
|
||||
* And the following optional values:
|
||||
*
|
||||
* char-type Valid options here are uint8 and int8. If uint8 is
|
||||
* specified this changes the default behavior of a single
|
||||
* char from being a buffer of a single character to being
|
||||
* a uint8_t. If int8, it becomes an int8_t instead.
|
||||
*/
|
||||
function CTypeParser(conf)
|
||||
{
|
||||
if (!conf) throw (new Error('missing required argument'));
|
||||
|
||||
if (!('endian' in conf))
|
||||
throw (new Error('missing required endian value'));
|
||||
|
||||
if (conf['endian'] != 'big' && conf['endian'] != 'little')
|
||||
throw (new Error('Invalid endian type'));
|
||||
|
||||
if ('char-type' in conf && (conf['char-type'] != 'uint8' &&
|
||||
conf['char-type'] != 'int8'))
|
||||
throw (new Error('invalid option for char-type: ' +
|
||||
conf['char-type']));
|
||||
|
||||
this.endian = conf['endian'];
|
||||
this.types = ctGetBasicTypes();
|
||||
|
||||
/*
|
||||
* There may be a more graceful way to do this, but this will have to
|
||||
* serve.
|
||||
*/
|
||||
if ('char-type' in conf && conf['char-type'] == 'uint8')
|
||||
this.types['char'] = this.types['uint8_t'];
|
||||
|
||||
if ('char-type' in conf && conf['char-type'] == 'int8')
|
||||
this.types['char'] = this.types['int8_t'];
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets the current endian value for the Parser. If the value is not valid,
|
||||
* throws an Error.
|
||||
*
|
||||
* endian Either 'big' or 'little' do determine the endianness we
|
||||
* want to read from or write to.
|
||||
*
|
||||
*/
|
||||
CTypeParser.prototype.setEndian = function (endian)
|
||||
{
|
||||
if (endian != 'big' && endian != 'little')
|
||||
throw (new Error('invalid endian type, must be big or ' +
|
||||
'little'));
|
||||
|
||||
this.endian = endian;
|
||||
};
|
||||
|
||||
/*
|
||||
* Returns the current value of the endian value for the parser.
|
||||
*/
|
||||
CTypeParser.prototype.getEndian = function ()
|
||||
{
|
||||
return (this.endian);
|
||||
};
|
||||
|
||||
/*
|
||||
* A user has requested to add a type, let us honor their request. Yet, if their
|
||||
* request doth spurn us, send them unto the Hells which Dante describes.
|
||||
*
|
||||
* name The string for the type definition we're adding
|
||||
*
|
||||
* value Either a string that is a type/array name or an object
|
||||
* that describes a struct.
|
||||
*/
|
||||
CTypeParser.prototype.typedef = function (name, value)
|
||||
{
|
||||
var type;
|
||||
|
||||
if (name === undefined)
|
||||
throw (new (Error('missing required typedef argument: name')));
|
||||
|
||||
if (value === undefined)
|
||||
throw (new (Error('missing required typedef argument: value')));
|
||||
|
||||
if (typeof (name) != 'string')
|
||||
throw (new (Error('the name of a type must be a string')));
|
||||
|
||||
type = ctParseType(name);
|
||||
|
||||
if (type['len'] !== undefined)
|
||||
throw (new Error('Cannot have an array in the typedef name'));
|
||||
|
||||
if (name in this.types)
|
||||
throw (new Error('typedef name already present: ' + name));
|
||||
|
||||
if (typeof (value) != 'string' && !(value instanceof Array))
|
||||
throw (new Error('typedef value must either be a string or ' +
|
||||
'struct'));
|
||||
|
||||
if (typeof (value) == 'string') {
|
||||
type = ctParseType(value);
|
||||
if (type['len'] !== undefined) {
|
||||
if (isNaN(parseInt(type['len'], 10)))
|
||||
throw (new (Error('typedef value must use ' +
|
||||
'fixed size array when outside of a ' +
|
||||
'struct')));
|
||||
}
|
||||
|
||||
this.types[name] = value;
|
||||
} else {
|
||||
/* We have a struct, validate it */
|
||||
ctCheckReq(value, this.types);
|
||||
this.types[name] = value;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Include all of the typedefs, but none of the built in types. This should be
|
||||
* treated as read-only.
|
||||
*/
|
||||
CTypeParser.prototype.lstypes = function ()
|
||||
{
|
||||
var key;
|
||||
var ret = {};
|
||||
|
||||
for (key in this.types) {
|
||||
if (key in deftypes)
|
||||
continue;
|
||||
ret[key] = this.types[key];
|
||||
}
|
||||
|
||||
return (ret);
|
||||
};
|
||||
|
||||
/*
|
||||
* Given a type string that may have array types that aren't numbers, try and
|
||||
* fill them in from the values object. The object should be of the format where
|
||||
* indexing into it should return a number for that type.
|
||||
*
|
||||
* str The type string
|
||||
*
|
||||
* values An object that can be used to fulfill type information
|
||||
*/
|
||||
function ctResolveArray(str, values)
|
||||
{
|
||||
var ret = '';
|
||||
var type = ctParseType(str);
|
||||
|
||||
while (type['len'] !== undefined) {
|
||||
if (isNaN(parseInt(type['len'], 10))) {
|
||||
if (typeof (values[type['len']]) != 'number')
|
||||
throw (new Error('cannot sawp in non-number ' +
|
||||
'for array value'));
|
||||
ret = '[' + values[type['len']] + ']' + ret;
|
||||
} else {
|
||||
ret = '[' + type['len'] + ']' + ret;
|
||||
}
|
||||
type = ctParseType(type['type']);
|
||||
}
|
||||
|
||||
ret = type['type'] + ret;
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* [private] Either the typedef resolves to another type string or to a struct.
|
||||
* If it resolves to a struct, we just pass it off to read struct. If not, we
|
||||
* can just pass it off to read entry.
|
||||
*/
|
||||
CTypeParser.prototype.resolveTypedef = function (type, dispatch, buffer,
|
||||
offset, value)
|
||||
{
|
||||
var pt;
|
||||
|
||||
mod_assert.ok(type in this.types);
|
||||
if (typeof (this.types[type]) == 'string') {
|
||||
pt = ctParseType(this.types[type]);
|
||||
if (dispatch == 'read')
|
||||
return (this.readEntry(pt, buffer, offset));
|
||||
else if (dispatch == 'write')
|
||||
return (this.writeEntry(value, pt, buffer, offset));
|
||||
else
|
||||
throw (new Error('invalid dispatch type to ' +
|
||||
'resolveTypedef'));
|
||||
} else {
|
||||
if (dispatch == 'read')
|
||||
return (this.readStruct(this.types[type], buffer,
|
||||
offset));
|
||||
else if (dispatch == 'write')
|
||||
return (this.writeStruct(value, this.types[type],
|
||||
buffer, offset));
|
||||
else
|
||||
throw (new Error('invalid dispatch type to ' +
|
||||
'resolveTypedef'));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
* [private] Try and read in the specific entry.
|
||||
*/
|
||||
CTypeParser.prototype.readEntry = function (type, buffer, offset)
|
||||
{
|
||||
var parse, len;
|
||||
|
||||
/*
|
||||
* Because we want to special case char[]s this is unfortunately
|
||||
* a bit uglier than it really should be. We want to special
|
||||
* case char[]s so that we return a node buffer, thus they are a
|
||||
* first class type where as all other arrays just call into a
|
||||
* generic array routine which calls their data-specific routine
|
||||
* the specified number of times.
|
||||
*
|
||||
* The valid dispatch options we have are:
|
||||
* - Array and char => char[] handler
|
||||
* - Generic array handler
|
||||
* - Generic typedef handler
|
||||
* - Basic type handler
|
||||
*/
|
||||
if (type['len'] !== undefined) {
|
||||
len = parseInt(type['len'], 10);
|
||||
if (isNaN(len))
|
||||
throw (new Error('somehow got a non-numeric length'));
|
||||
|
||||
if (type['type'] == 'char')
|
||||
parse = this.types['char[]']['read'](len,
|
||||
this.endian, buffer, offset);
|
||||
else
|
||||
parse = this.readArray(type['type'],
|
||||
len, buffer, offset);
|
||||
} else {
|
||||
if (type['type'] in deftypes)
|
||||
parse = this.types[type['type']]['read'](this.endian,
|
||||
buffer, offset);
|
||||
else
|
||||
parse = this.resolveTypedef(type['type'], 'read',
|
||||
buffer, offset);
|
||||
}
|
||||
|
||||
return (parse);
|
||||
};
|
||||
|
||||
/*
|
||||
* [private] Read an array of data
|
||||
*/
|
||||
CTypeParser.prototype.readArray = function (type, length, buffer, offset)
|
||||
{
|
||||
var ii, ent, pt;
|
||||
var baseOffset = offset;
|
||||
var ret = new Array(length);
|
||||
pt = ctParseType(type);
|
||||
|
||||
for (ii = 0; ii < length; ii++) {
|
||||
ent = this.readEntry(pt, buffer, offset);
|
||||
offset += ent['size'];
|
||||
ret[ii] = ent['value'];
|
||||
}
|
||||
|
||||
return ({ value: ret, size: offset - baseOffset });
|
||||
};
|
||||
|
||||
/*
|
||||
* [private] Read a single struct in.
|
||||
*/
|
||||
CTypeParser.prototype.readStruct = function (def, buffer, offset)
|
||||
{
|
||||
var parse, ii, type, entry, key;
|
||||
var baseOffset = offset;
|
||||
var ret = {};
|
||||
|
||||
/* Walk it and handle doing what's necessary */
|
||||
for (ii = 0; ii < def.length; ii++) {
|
||||
key = Object.keys(def[ii])[0];
|
||||
entry = def[ii][key];
|
||||
|
||||
/* Resolve all array values */
|
||||
type = ctParseType(ctResolveArray(entry['type'], ret));
|
||||
|
||||
if ('offset' in entry)
|
||||
offset = baseOffset + entry['offset'];
|
||||
|
||||
parse = this.readEntry(type, buffer, offset);
|
||||
|
||||
offset += parse['size'];
|
||||
ret[key] = parse['value'];
|
||||
}
|
||||
|
||||
return ({ value: ret, size: (offset-baseOffset)});
|
||||
};
|
||||
|
||||
/*
|
||||
* This is what we were born to do. We read the data from a buffer and return it
|
||||
* in an object whose keys match the values from the object.
|
||||
*
|
||||
* def The array definition of the data to read in
|
||||
*
|
||||
* buffer The buffer to read data from
|
||||
*
|
||||
* offset The offset to start writing to
|
||||
*
|
||||
* Returns an object where each key corresponds to an entry in def and the value
|
||||
* is the read value.
|
||||
*/
|
||||
CTypeParser.prototype.readData = function (def, buffer, offset)
|
||||
{
|
||||
/* Sanity check for arguments */
|
||||
if (def === undefined)
|
||||
throw (new Error('missing definition for what we should be' +
|
||||
'parsing'));
|
||||
|
||||
if (buffer === undefined)
|
||||
throw (new Error('missing buffer for what we should be ' +
|
||||
'parsing'));
|
||||
|
||||
if (offset === undefined)
|
||||
throw (new Error('missing offset for what we should be ' +
|
||||
'parsing'));
|
||||
|
||||
/* Sanity check the object definition */
|
||||
ctCheckReq(def, this.types);
|
||||
|
||||
return (this.readStruct(def, buffer, offset)['value']);
|
||||
};
|
||||
|
||||
/*
|
||||
* [private] Write out an array of data
|
||||
*/
|
||||
CTypeParser.prototype.writeArray = function (value, type, length, buffer,
|
||||
offset)
|
||||
{
|
||||
var ii, pt;
|
||||
var baseOffset = offset;
|
||||
if (!(value instanceof Array))
|
||||
throw (new Error('asked to write an array, but value is not ' +
|
||||
'an array'));
|
||||
|
||||
if (value.length != length)
|
||||
throw (new Error('asked to write array of length ' + length +
|
||||
' but that does not match value length: ' + value.length));
|
||||
|
||||
pt = ctParseType(type);
|
||||
for (ii = 0; ii < length; ii++)
|
||||
offset += this.writeEntry(value[ii], pt, buffer, offset);
|
||||
|
||||
return (offset - baseOffset);
|
||||
};
|
||||
|
||||
/*
|
||||
* [private] Write the specific entry
|
||||
*/
|
||||
CTypeParser.prototype.writeEntry = function (value, type, buffer, offset)
|
||||
{
|
||||
var len, ret;
|
||||
|
||||
if (type['len'] !== undefined) {
|
||||
len = parseInt(type['len'], 10);
|
||||
if (isNaN(len))
|
||||
throw (new Error('somehow got a non-numeric length'));
|
||||
|
||||
if (type['type'] == 'char')
|
||||
ret = this.types['char[]']['write'](value, len,
|
||||
this.endian, buffer, offset);
|
||||
else
|
||||
ret = this.writeArray(value, type['type'],
|
||||
len, buffer, offset);
|
||||
} else {
|
||||
if (type['type'] in deftypes)
|
||||
ret = this.types[type['type']]['write'](value,
|
||||
this.endian, buffer, offset);
|
||||
else
|
||||
ret = this.resolveTypedef(type['type'], 'write',
|
||||
buffer, offset, value);
|
||||
}
|
||||
|
||||
return (ret);
|
||||
};
|
||||
|
||||
/*
|
||||
* [private] Write a single struct out.
|
||||
*/
|
||||
CTypeParser.prototype.writeStruct = function (value, def, buffer, offset)
|
||||
{
|
||||
var ii, entry, type, key;
|
||||
var baseOffset = offset;
|
||||
var vals = {};
|
||||
|
||||
for (ii = 0; ii < def.length; ii++) {
|
||||
key = Object.keys(def[ii])[0];
|
||||
entry = def[ii][key];
|
||||
|
||||
type = ctParseType(ctResolveArray(entry['type'], vals));
|
||||
|
||||
if ('offset' in entry)
|
||||
offset = baseOffset + entry['offset'];
|
||||
|
||||
offset += this.writeEntry(value[ii], type, buffer, offset);
|
||||
/* Now that we've written it out, we can use it for arrays */
|
||||
vals[key] = value[ii];
|
||||
}
|
||||
|
||||
return (offset);
|
||||
};
|
||||
|
||||
/*
|
||||
* Unfortunately, we're stuck with the sins of an initial poor design. Because
|
||||
* of that, we are going to have to support the old way of writing data via
|
||||
* writeData. There we insert the values that you want to write into the
|
||||
* definition. A little baroque. Internally, we use the new model. So we need to
|
||||
* just get those values out of there. But to maintain the principle of least
|
||||
* surprise, we're not going to modify the input data.
|
||||
*/
|
||||
function getValues(def)
|
||||
{
|
||||
var ii, out, key;
|
||||
out = [];
|
||||
for (ii = 0; ii < def.length; ii++) {
|
||||
key = Object.keys(def[ii])[0];
|
||||
mod_assert.ok('value' in def[ii][key]);
|
||||
out.push(def[ii][key]['value']);
|
||||
}
|
||||
|
||||
return (out);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the second half of what we were born to do, write out the data
|
||||
* itself. Historically this function required you to put your values in the
|
||||
* definition section. This was not the smartest thing to do and a bit of an
|
||||
* oversight to be honest. As such, this function now takes a values argument.
|
||||
* If values is non-null and non-undefined, it will be used to determine the
|
||||
* values. This means that the old method is still supported, but is no longer
|
||||
* acceptable.
|
||||
*
|
||||
* def The array definition of the data to write out with
|
||||
* values
|
||||
*
|
||||
* buffer The buffer to write to
|
||||
*
|
||||
* offset The offset in the buffer to write to
|
||||
*
|
||||
* values An array of values to write.
|
||||
*/
|
||||
CTypeParser.prototype.writeData = function (def, buffer, offset, values)
|
||||
{
|
||||
var hv;
|
||||
|
||||
if (def === undefined)
|
||||
throw (new Error('missing definition for what we should be' +
|
||||
'parsing'));
|
||||
|
||||
if (buffer === undefined)
|
||||
throw (new Error('missing buffer for what we should be ' +
|
||||
'parsing'));
|
||||
|
||||
if (offset === undefined)
|
||||
throw (new Error('missing offset for what we should be ' +
|
||||
'parsing'));
|
||||
|
||||
hv = (values != null && values != undefined);
|
||||
if (hv) {
|
||||
if (!Array.isArray(values))
|
||||
throw (new Error('missing values for writing'));
|
||||
ctCheckReq(def, this.types);
|
||||
} else {
|
||||
ctCheckReq(def, this.types, [ 'value' ]);
|
||||
}
|
||||
|
||||
this.writeStruct(hv ? values : getValues(def), def, buffer, offset);
|
||||
};
|
||||
|
||||
/*
|
||||
* Functions to go to and from 64 bit numbers in a way that is compatible with
|
||||
* Javascript limitations. There are two sets. One where the user is okay with
|
||||
* an approximation and one where they are definitely not okay with an
|
||||
* approximation.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Attempts to convert an array of two integers returned from rsint64 / ruint64
|
||||
* into an absolute 64 bit number. If however the value would exceed 2^52 this
|
||||
* will instead throw an error. The mantissa in a double is a 52 bit number and
|
||||
* rather than potentially give you a value that is an approximation this will
|
||||
* error. If you would rather an approximation, please see toApprox64.
|
||||
*
|
||||
* val An array of two 32-bit integers
|
||||
*/
|
||||
function toAbs64(val)
|
||||
{
|
||||
if (val === undefined)
|
||||
throw (new Error('missing required arg: value'));
|
||||
|
||||
if (!Array.isArray(val))
|
||||
throw (new Error('value must be an array'));
|
||||
|
||||
if (val.length != 2)
|
||||
throw (new Error('value must be an array of length 2'));
|
||||
|
||||
/* We have 20 bits worth of precision in this range */
|
||||
if (val[0] >= 0x100000)
|
||||
throw (new Error('value would become approximated'));
|
||||
|
||||
return (val[0] * Math.pow(2, 32) + val[1]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Will return the 64 bit value as returned in an array from rsint64 / ruint64
|
||||
* to a value as close as it can. Note that Javascript stores all numbers as a
|
||||
* double and the mantissa only has 52 bits. Thus this version may approximate
|
||||
* the value.
|
||||
*
|
||||
* val An array of two 32-bit integers
|
||||
*/
|
||||
function toApprox64(val)
|
||||
{
|
||||
if (val === undefined)
|
||||
throw (new Error('missing required arg: value'));
|
||||
|
||||
if (!Array.isArray(val))
|
||||
throw (new Error('value must be an array'));
|
||||
|
||||
if (val.length != 2)
|
||||
throw (new Error('value must be an array of length 2'));
|
||||
|
||||
return (Math.pow(2, 32) * val[0] + val[1]);
|
||||
}
|
||||
|
||||
function parseCTF(json, conf)
|
||||
{
|
||||
var ctype = new CTypeParser(conf);
|
||||
mod_ctf.ctfParseJson(json, ctype);
|
||||
|
||||
return (ctype);
|
||||
}
|
||||
|
||||
/*
|
||||
* Export the few things we actually want to. Currently this is just the CType
|
||||
* Parser and ctio.
|
||||
*/
|
||||
exports.Parser = CTypeParser;
|
||||
exports.toAbs64 = toAbs64;
|
||||
exports.toApprox64 = toApprox64;
|
||||
|
||||
exports.parseCTF = parseCTF;
|
||||
|
||||
exports.ruint8 = mod_ctio.ruint8;
|
||||
exports.ruint16 = mod_ctio.ruint16;
|
||||
exports.ruint32 = mod_ctio.ruint32;
|
||||
exports.ruint64 = mod_ctio.ruint64;
|
||||
exports.wuint8 = mod_ctio.wuint8;
|
||||
exports.wuint16 = mod_ctio.wuint16;
|
||||
exports.wuint32 = mod_ctio.wuint32;
|
||||
exports.wuint64 = mod_ctio.wuint64;
|
||||
|
||||
exports.rsint8 = mod_ctio.rsint8;
|
||||
exports.rsint16 = mod_ctio.rsint16;
|
||||
exports.rsint32 = mod_ctio.rsint32;
|
||||
exports.rsint64 = mod_ctio.rsint64;
|
||||
exports.wsint8 = mod_ctio.wsint8;
|
||||
exports.wsint16 = mod_ctio.wsint16;
|
||||
exports.wsint32 = mod_ctio.wsint32;
|
||||
exports.wsint64 = mod_ctio.wsint64;
|
||||
|
||||
exports.rfloat = mod_ctio.rfloat;
|
||||
exports.rdouble = mod_ctio.rdouble;
|
||||
exports.wfloat = mod_ctio.wfloat;
|
||||
exports.wdouble = mod_ctio.wdouble;
|
||||
241
node_modules/ctype/man/man3ctype/ctio.3ctype
generated
vendored
Normal file
241
node_modules/ctype/man/man3ctype/ctio.3ctype
generated
vendored
Normal file
@@ -0,0 +1,241 @@
|
||||
'\" te
|
||||
.\" Copyright (c) 2011, Robert Mustacchi. All Rights Reserved.
|
||||
.\" Copyright (c) 2011, Joyent, Inc. All Rights Reserved.
|
||||
.\"
|
||||
.\" 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.
|
||||
.TH CTIO 3CTYPE "December 12, 2011"
|
||||
.SH NAME
|
||||
ctio, ruint8, ruint16, ruint32, ruint64, wuint8, wuint16, wuint32, wuint64,
|
||||
rsint8, rsint16, rsint32, rsint64, wsint8, wsint16, wsint32, wsint64, rfloat,
|
||||
rdouble, wfloat, wdouble \- integer and float operations
|
||||
.SH SYNOPSIS
|
||||
.LP
|
||||
.nf
|
||||
var mod_ctype = require('ctype');
|
||||
|
||||
\fBNumber\fR \fBmod_ctype.ruint8\fR(\fBBuffer\fR \fIbuf\fR, \fBString\fR \fIendian\fR, \fBNumber\fR \fIoffset\fR);
|
||||
.fi
|
||||
|
||||
.LP
|
||||
.nf
|
||||
\fBNumber\fR \fBmod_ctype.ruint16\fR(\fBBuffer\fR \fIbuf\fR, \fBString\fR \fIendian\fR, \fBNumber\fR \fIoffset\fR);
|
||||
.fi
|
||||
|
||||
.LP
|
||||
.nf
|
||||
\fBNumber\fR \fBmod_ctype.ruint32\fR(\fBBuffer\fR \fIbuf\fR, \fBString\fR \fIendian\fR, \fBNumber\fR \fIoffset\fR);
|
||||
.fi
|
||||
|
||||
.LP
|
||||
.nf
|
||||
\fBNumber[2]\fR \fBmod_ctype.ruint64\fR(\fBBuffer\fR \fIbuf\fR, \fBString\fR \fIendian\fR, \fBNumber\fR \fIoffset\fR);
|
||||
.fi
|
||||
|
||||
.LP
|
||||
.nf
|
||||
\fBNumber\fR \fBmod_ctype.rsint8\fR(\fBBuffer\fR \fIbuf\fR, \fBString\fR \fIendian\fR, \fBNumber\fR \fIoffset\fR);
|
||||
.fi
|
||||
|
||||
.LP
|
||||
.nf
|
||||
\fBNumber\fR \fBmod_ctype.rsint16\fR(\fBBuffer\fR \fIbuf\fR, \fBString\fR \fIendian\fR, \fBNumber\fR \fIoffset\fR);
|
||||
.fi
|
||||
|
||||
.LP
|
||||
.nf
|
||||
\fBNumber\fR \fBmod_ctype.rsint32\fR(\fBBuffer\fR \fIbuf\fR, \fBString\fR \fIendian\fR, \fBNumber\fR \fIoffset\fR);
|
||||
.fi
|
||||
|
||||
.LP
|
||||
.nf
|
||||
\fBNumber[2]\fR \fBmod_ctype.rsint64\fR(\fBBuffer\fR \fIbuf\fR, \fBString\fR \fIendian\fR, \fBNumber\fR \fIoffset\fR);
|
||||
.fi
|
||||
|
||||
.LP
|
||||
.nf
|
||||
\fBNumber\fR \fBmod_ctype.rfloat\fR(\fBBuffer\fR \fIbuf\fR, \fBString\fR \fIendian\fR, \fBNumber\fR \fIoffset\fR);
|
||||
.fi
|
||||
|
||||
.LP
|
||||
.nf
|
||||
\fBNumber\fR \fBmod_ctype.rdouble\fR(\fBBuffer\fR \fIbuf\fR, \fBString\fR \fIendian\fR, \fBNumber\fR \fIoffset\fR);
|
||||
.fi
|
||||
|
||||
.LP
|
||||
.nf
|
||||
\fBvoid\fR \fBmod_ctype.wuint8\fR(\fBNumber\fR value, \fBString\fR \fIendian\fR, \fBBuffer\fR \fIbuf\fR, \fBNumber\fR \fIoffset\fR);
|
||||
.fi
|
||||
|
||||
.LP
|
||||
.nf
|
||||
\fBvoid\fR \fBmod_ctype.wuint16\fR(\fBNumber\fR value, \fBString\fR \fIendian\fR, \fBBuffer\fR \fIbuf\fR, \fBNumber\fR \fIoffset\fR);
|
||||
.fi
|
||||
|
||||
.LP
|
||||
.nf
|
||||
\fBvoid\fR \fBmod_ctype.wuint32\fR(\fBNumber\fR value, \fBString\fR \fIendian\fR, \fBBuffer\fR \fIbuf\fR, \fBNumber\fR \fIoffset\fR);
|
||||
.fi
|
||||
|
||||
.LP
|
||||
.nf
|
||||
\fBvoid\fR \fBmod_ctype.wuint64\fR(\fBNumber[2]\fR value, \fBString\fR \fIendian\fR, \fBBuffer\fR \fIbuf\fR, \fBNumber\fR \fIoffset\fR);
|
||||
.fi
|
||||
|
||||
.LP
|
||||
.nf
|
||||
\fBvoid\fR \fBmod_ctype.wsint8\fR(\fBNumber\fR value, \fBString\fR \fIendian\fR, \fBBuffer\fR \fIbuf\fR, \fBNumber\fR \fIoffset\fR);
|
||||
.fi
|
||||
|
||||
.LP
|
||||
.nf
|
||||
\fBvoid\fR \fBmod_ctype.wsint16\fR(\fBNumber\fR value, \fBString\fR \fIendian\fR, \fBBuffer\fR \fIbuf\fR, \fBNumber\fR \fIoffset\fR);
|
||||
.fi
|
||||
|
||||
.LP
|
||||
.nf
|
||||
\fBvoid\fR \fBmod_ctype.wsint32\fR(\fBNumber\fR value, \fBString\fR \fIendian\fR, \fBBuffer\fR \fIbuf\fR, \fBNumber\fR \fIoffset\fR);
|
||||
.fi
|
||||
|
||||
.LP
|
||||
.nf
|
||||
\fBvoid\fR \fBmod_ctype.wsint64\fR(\fBNumber[2]\fR value, \fBString\fR \fIendian\fR, \fBBuffer\fR \fIbuf\fR, \fBNumber\fR \fIoffset\fR);
|
||||
.fi
|
||||
|
||||
.LP
|
||||
.nf
|
||||
\fBvoid\fR \fBmod_ctype.wfloat\fR(\fBNumber\fR value, \fBString\fR \fIendian\fR, \fBBuffer\fR \fIbuf\fR, \fBNumber\fR \fIoffset\fR);
|
||||
.fi
|
||||
|
||||
.LP
|
||||
.nf
|
||||
\fBvoid\fR \fBmod_ctype.wdouble\fR(\fBNumber\fR value, \fBString\fR \fIendian\fR, \fBBuffer\fR \fIbuf\fR, \fBNumber\fR \fIoffset\fR);
|
||||
.fi
|
||||
|
||||
.SH DESCRIPTION
|
||||
.sp
|
||||
.LP
|
||||
The argument \fIbuf\fR refers to a valid buffer (from calling new Buffer()). The
|
||||
argument \fIendian\fR is either the string 'big' or 'little' and controls
|
||||
whether the data in the buffer is interpreted as big or little endian. The argument
|
||||
\fIoffset\fR indicates the starting index into the buffer to read or write. All
|
||||
functions ensure that starting at \fIoffset\fR does not overflow the end of the
|
||||
buffer. The argument \fIvalue\fR is a Number that is the valid type for the
|
||||
specific function. All functions that take \fIvalue\fR as an argument, verify
|
||||
that the passed value is valid.
|
||||
|
||||
.SS "\fBruint8()\fR, \fBruint16()\fR, \fBruint32()\fR"
|
||||
.sp
|
||||
.LP
|
||||
The \fBruint8()\fR, \fBruint16()\fR, and \fBruint32()\fR functions read an 8,
|
||||
16, and 32-bit unsigned value from \fIbuf\fR and return it. The value read is
|
||||
influenced by the values of \fIoffset\fR and \fRendian\fI.
|
||||
|
||||
|
||||
.SS "\fBrsint8()\fR, \fBrsint16()\fR, \fBrsint32()\fR"
|
||||
.sp
|
||||
.LP
|
||||
The \fBruint8()\fR, \fBruint16()\fR, and \fBruint32()\fR functions work just as
|
||||
\fBruint8()\fR, \fBruint16()\fR, and \fBruint32()\fR, except they return signed
|
||||
integers.
|
||||
|
||||
.SS "\fBruint64()\fR, \fBrsint64()\fR"
|
||||
.sp
|
||||
.LP
|
||||
The \fBruint64()\fR and \fBrsint64()\fR functions read unsigned and signed 64
|
||||
bit integers respectively from \fBbuf\fR. Due to the limitations of ECMAScript's
|
||||
\fBNumber\fR type, they cannot be stored as one value without a loss of
|
||||
precision. Instead of returning the values as a single \fBNumber\fR, the
|
||||
functions return an array of two numbers. The first entry always contains the
|
||||
upper 32-bits and the second value contains the lower 32-bits. The lossy
|
||||
transformation into a number would be \fIres[0]*Math.pow(2,32)+res[1]\fR.
|
||||
Note that, unless an entry is zero, both array entries are guaranteed to have
|
||||
the same sign.
|
||||
|
||||
.SS "\fBwuint8()\fR, \fBwuint16()\fR, \fBwuint32()\fR"
|
||||
.sp
|
||||
.LP
|
||||
The functions \fBwuint8()\fR, \fBwuint16()\fR, and \fBwuint32()\fR modify the
|
||||
contents of \fBbuf\fR by writing an 8, 16, and 32-bit unsigned integer
|
||||
respectively to \fBbuf\fR. It is illegal to pass a number that is not an integer
|
||||
within the domain of the integer size, for example, for \fBwuint8()\fR the valid
|
||||
range is \fB[0, 255]\fR. The value will be written in either big or little
|
||||
endian format based upon the value of \fBendian\fR.
|
||||
|
||||
|
||||
.SS "\fBwsint8()\fR, \fBwsint16()\fR, \fBwsint32()\fR"
|
||||
.sp
|
||||
.LP
|
||||
The functions \fBwsint8()\fR, \fBwsint16()\fR, and \fBwsint32()\fR function
|
||||
identically to the functions \fBwuint8()\fR, \fBwuint16()\fR, and
|
||||
\fBwuint32()\fR except that they the valid domain for \fBvalue\fR is that of a
|
||||
signed number instead of an unsigned number. For example the \fBwsint8()\fR has
|
||||
a domain of \fB[-128, 127]\fR.
|
||||
|
||||
.SS "\fBwuint64()\fR, \fBwsint64()\fR"
|
||||
.sp
|
||||
.LP
|
||||
The functions \fBwuint64()\fR and \fBswint64()\fR write out 64-bit unsigned and
|
||||
signed integers to \fBbuf\fR. The \fBvalue\fR argument must be in the same
|
||||
format as described in \fBruint64()\fR and \fBrsint64()\fR.
|
||||
|
||||
.SS "\fBrfloat()\fR, \fBrdouble()\fR"
|
||||
.sp
|
||||
.LP
|
||||
The functions "\fBrfloat()\fR and \fBrdouble()\fR" work like the other read
|
||||
functions, except that they read a single precision and double precision
|
||||
IEEE-754 floating point value instead.
|
||||
|
||||
.SS "\fBwfloat()\fR, \fBwdouble()\fR"
|
||||
.sp
|
||||
.LP
|
||||
The functions "\fBrfloat()\fR and \fBrdouble()\fR" work like the other write
|
||||
functions, except that the domain for a float is that of a single precision 4
|
||||
byte value. The domain for a double is any \fBNumber\fR in ECMAScript, which is
|
||||
defined to be represented by a double.
|
||||
|
||||
.SH ATTRIBUTES
|
||||
.sp
|
||||
.LP
|
||||
See \fBattributes\fR(5) for descriptions of the following attributes:
|
||||
.sp
|
||||
|
||||
.sp
|
||||
.TS
|
||||
box;
|
||||
c | c
|
||||
l | l .
|
||||
ATTRIBUTE TYPE ATTRIBUTE VALUE
|
||||
_
|
||||
Interface Stability Committed
|
||||
_
|
||||
MT-Level See below.
|
||||
_
|
||||
Standard Not standardized.
|
||||
.TE
|
||||
|
||||
.sp
|
||||
.LP
|
||||
|
||||
All functions are MT-safe in so far as there aren't shared memory MT concerns in
|
||||
most node programs. If one where to concoct such an environment, these functions
|
||||
wouldn't be MT-safe.
|
||||
|
||||
.SH SEE ALSO
|
||||
.sp
|
||||
.LP
|
||||
76
node_modules/ctype/package.json
generated
vendored
Normal file
76
node_modules/ctype/package.json
generated
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
{
|
||||
"_args": [
|
||||
[
|
||||
{
|
||||
"name": "ctype",
|
||||
"raw": "ctype@0.5.3",
|
||||
"rawSpec": "0.5.3",
|
||||
"scope": null,
|
||||
"spec": "0.5.3",
|
||||
"type": "version"
|
||||
},
|
||||
"C:\\Users\\talor\\bots\\polibug\\node_modules\\http-signature"
|
||||
]
|
||||
],
|
||||
"_from": "ctype@0.5.3",
|
||||
"_id": "ctype@0.5.3",
|
||||
"_inCache": true,
|
||||
"_installable": true,
|
||||
"_location": "/ctype",
|
||||
"_npmUser": {
|
||||
"email": "rm@fingolfin.org",
|
||||
"name": "rm"
|
||||
},
|
||||
"_npmVersion": "1.1.59",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"name": "ctype",
|
||||
"raw": "ctype@0.5.3",
|
||||
"rawSpec": "0.5.3",
|
||||
"scope": null,
|
||||
"spec": "0.5.3",
|
||||
"type": "version"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/http-signature"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/ctype/-/ctype-0.5.3.tgz",
|
||||
"_shasum": "82c18c2461f74114ef16c135224ad0b9144ca12f",
|
||||
"_shrinkwrap": null,
|
||||
"_spec": "ctype@0.5.3",
|
||||
"_where": "C:\\Users\\talor\\bots\\polibug\\node_modules\\http-signature",
|
||||
"author": {
|
||||
"email": "rm@fingolfin.org",
|
||||
"name": "Robert Mustacchi"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/rmustacc/node-ctype/issues"
|
||||
},
|
||||
"dependencies": {},
|
||||
"description": "read and write binary structures and data types",
|
||||
"devDependencies": {},
|
||||
"directories": {},
|
||||
"dist": {
|
||||
"shasum": "82c18c2461f74114ef16c135224ad0b9144ca12f",
|
||||
"tarball": "https://registry.npmjs.org/ctype/-/ctype-0.5.3.tgz"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"homepage": "https://github.com/rmustacc/node-ctype",
|
||||
"main": "ctype.js",
|
||||
"maintainers": [
|
||||
{
|
||||
"email": "rm@fingolfin.org",
|
||||
"name": "rm"
|
||||
}
|
||||
],
|
||||
"name": "ctype",
|
||||
"optionalDependencies": {},
|
||||
"readme": "ERROR: No README data found!",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/rmustacc/node-ctype.git"
|
||||
},
|
||||
"version": "0.5.3"
|
||||
}
|
||||
129
node_modules/ctype/tools/jsl.conf
generated
vendored
Normal file
129
node_modules/ctype/tools/jsl.conf
generated
vendored
Normal file
@@ -0,0 +1,129 @@
|
||||
#
|
||||
# Configuration File for JavaScript Lint 0.3.0
|
||||
# Developed by Matthias Miller (http://www.JavaScriptLint.com)
|
||||
#
|
||||
# This configuration file can be used to lint a collection of scripts, or to enable
|
||||
# or disable warnings for scripts that are linted via the command line.
|
||||
#
|
||||
|
||||
### Warnings
|
||||
# Enable or disable warnings based on requirements.
|
||||
# Use "+WarningName" to display or "-WarningName" to suppress.
|
||||
#
|
||||
+no_return_value # function {0} does not always return a value
|
||||
+duplicate_formal # duplicate formal argument {0}
|
||||
+equal_as_assign # test for equality (==) mistyped as assignment (=)?{0}
|
||||
+var_hides_arg # variable {0} hides argument
|
||||
+redeclared_var # redeclaration of {0} {1}
|
||||
+anon_no_return_value # anonymous function does not always return a value
|
||||
+missing_semicolon # missing semicolon
|
||||
+meaningless_block # meaningless block; curly braces have no impact
|
||||
+comma_separated_stmts # multiple statements separated by commas (use semicolons?)
|
||||
+unreachable_code # unreachable code
|
||||
+missing_break # missing break statement
|
||||
+missing_break_for_last_case # missing break statement for last case in switch
|
||||
+comparison_type_conv # comparisons against null, 0, true, false, or an empty string allowing implicit type conversion (use === or !==)
|
||||
-inc_dec_within_stmt # increment (++) and decrement (--) operators used as part of greater statement
|
||||
+useless_void # use of the void type may be unnecessary (void is always undefined)
|
||||
-useless_quotes # quotation marks are unnecessary
|
||||
+multiple_plus_minus # unknown order of operations for successive plus (e.g. x+++y) or minus (e.g. x---y) signs
|
||||
+use_of_label # use of label
|
||||
-block_without_braces # block statement without curly braces
|
||||
+leading_decimal_point # leading decimal point may indicate a number or an object member
|
||||
+trailing_decimal_point # trailing decimal point may indicate a number or an object member
|
||||
-octal_number # leading zeros make an octal number
|
||||
+nested_comment # nested comment
|
||||
+misplaced_regex # regular expressions should be preceded by a left parenthesis, assignment, colon, or comma
|
||||
+ambiguous_newline # unexpected end of line; it is ambiguous whether these lines are part of the same statement
|
||||
+empty_statement # empty statement or extra semicolon
|
||||
-missing_option_explicit # the "option explicit" control comment is missing
|
||||
+partial_option_explicit # the "option explicit" control comment, if used, must be in the first script tag
|
||||
+dup_option_explicit # duplicate "option explicit" control comment
|
||||
+useless_assign # useless assignment
|
||||
+ambiguous_nested_stmt # block statements containing block statements should use curly braces to resolve ambiguity
|
||||
+ambiguous_else_stmt # the else statement could be matched with one of multiple if statements (use curly braces to indicate intent)
|
||||
+missing_default_case # missing default case in switch statement
|
||||
+duplicate_case_in_switch # duplicate case in switch statements
|
||||
+default_not_at_end # the default case is not at the end of the switch statement
|
||||
+legacy_cc_not_understood # couldn't understand control comment using /*@keyword@*/ syntax
|
||||
+jsl_cc_not_understood # couldn't understand control comment using /*jsl:keyword*/ syntax
|
||||
+useless_comparison # useless comparison; comparing identical expressions
|
||||
+with_statement # with statement hides undeclared variables; use temporary variable instead
|
||||
+trailing_comma_in_array # extra comma is not recommended in array initializers
|
||||
+assign_to_function_call # assignment to a function call
|
||||
+parseint_missing_radix # parseInt missing radix parameter
|
||||
-unreferenced_argument # argument declared but never referenced: {name}
|
||||
|
||||
### Output format
|
||||
# Customize the format of the error message.
|
||||
# __FILE__ indicates current file path
|
||||
# __FILENAME__ indicates current file name
|
||||
# __LINE__ indicates current line
|
||||
# __ERROR__ indicates error message
|
||||
#
|
||||
# Visual Studio syntax (default):
|
||||
+output-format __FILE__(__LINE__): __ERROR__
|
||||
# Alternative syntax:
|
||||
#+output-format __FILE__:__LINE__: __ERROR__
|
||||
|
||||
|
||||
### Context
|
||||
# Show the in-line position of the error.
|
||||
# Use "+context" to display or "-context" to suppress.
|
||||
#
|
||||
+context
|
||||
|
||||
|
||||
### Semicolons
|
||||
# By default, assignments of an anonymous function to a variable or
|
||||
# property (such as a function prototype) must be followed by a semicolon.
|
||||
#
|
||||
#+lambda_assign_requires_semicolon # deprecated setting
|
||||
|
||||
|
||||
### Control Comments
|
||||
# Both JavaScript Lint and the JScript interpreter confuse each other with the syntax for
|
||||
# the /*@keyword@*/ control comments and JScript conditional comments. (The latter is
|
||||
# enabled in JScript with @cc_on@). The /*jsl:keyword*/ syntax is preferred for this reason,
|
||||
# although legacy control comments are enabled by default for backward compatibility.
|
||||
#
|
||||
+legacy_control_comments
|
||||
|
||||
|
||||
### JScript Function Extensions
|
||||
# JScript allows member functions to be defined like this:
|
||||
# function MyObj() { /*constructor*/ }
|
||||
# function MyObj.prototype.go() { /*member function*/ }
|
||||
#
|
||||
# It also allows events to be attached like this:
|
||||
# function window::onload() { /*init page*/ }
|
||||
#
|
||||
# This is a Microsoft-only JavaScript extension. Enable this setting to allow them.
|
||||
#
|
||||
#-jscript_function_extensions # deprecated setting
|
||||
|
||||
|
||||
### Defining identifiers
|
||||
# By default, "option explicit" is enabled on a per-file basis.
|
||||
# To enable this for all files, use "+always_use_option_explicit"
|
||||
-always_use_option_explicit
|
||||
|
||||
# Define certain identifiers of which the lint is not aware.
|
||||
# (Use this in conjunction with the "undeclared identifier" warning.)
|
||||
#
|
||||
# Common uses for webpages might be:
|
||||
#+define window
|
||||
#+define document
|
||||
+define require
|
||||
+define exports
|
||||
+define console
|
||||
+define Buffer
|
||||
+define JSON
|
||||
|
||||
### Files
|
||||
# Specify which files to lint
|
||||
# Use "+recurse" to enable recursion (disabled by default).
|
||||
# To add a set of files, use "+process FileName", "+process Folder\Path\*.js",
|
||||
# or "+process Folder\Path\*.htm".
|
||||
#
|
||||
#+process jsl-test.js
|
||||
839
node_modules/ctype/tools/jsstyle
generated
vendored
Normal file
839
node_modules/ctype/tools/jsstyle
generated
vendored
Normal file
@@ -0,0 +1,839 @@
|
||||
#!/usr/bin/env perl
|
||||
#
|
||||
# CDDL HEADER START
|
||||
#
|
||||
# The contents of this file are subject to the terms of the
|
||||
# Common Development and Distribution License (the "License").
|
||||
# You may not use this file except in compliance with the License.
|
||||
#
|
||||
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
# or http://www.opensolaris.org/os/licensing.
|
||||
# See the License for the specific language governing permissions
|
||||
# and limitations under the License.
|
||||
#
|
||||
# When distributing Covered Code, include this CDDL HEADER in each
|
||||
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
# If applicable, add the following below this CDDL HEADER, with the
|
||||
# fields enclosed by brackets "[]" replaced with your own identifying
|
||||
# information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
#
|
||||
# CDDL HEADER END
|
||||
#
|
||||
#
|
||||
# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
# Use is subject to license terms.
|
||||
#
|
||||
# Copyright 2011 Joyent, Inc. All rights reserved.
|
||||
#
|
||||
# jsstyle - check for some common stylistic errors.
|
||||
#
|
||||
# jsstyle is a sort of "lint" for Javascript coding style. This tool is
|
||||
# derived from the cstyle tool, used to check for the style used in the
|
||||
# Solaris kernel, sometimes known as "Bill Joy Normal Form".
|
||||
#
|
||||
# There's a lot this can't check for, like proper indentation of code
|
||||
# blocks. There's also a lot more this could check for.
|
||||
#
|
||||
# A note to the non perl literate:
|
||||
#
|
||||
# perl regular expressions are pretty much like egrep
|
||||
# regular expressions, with the following special symbols
|
||||
#
|
||||
# \s any space character
|
||||
# \S any non-space character
|
||||
# \w any "word" character [a-zA-Z0-9_]
|
||||
# \W any non-word character
|
||||
# \d a digit [0-9]
|
||||
# \D a non-digit
|
||||
# \b word boundary (between \w and \W)
|
||||
# \B non-word boundary
|
||||
#
|
||||
|
||||
require 5.0;
|
||||
use IO::File;
|
||||
use Getopt::Std;
|
||||
use strict;
|
||||
|
||||
my $usage =
|
||||
"usage: jsstyle [-chvC] [-o constructs] file ...
|
||||
-c check continuation indentation inside functions
|
||||
-h perform heuristic checks that are sometimes wrong
|
||||
-v verbose
|
||||
-C don't check anything in header block comments
|
||||
-o constructs
|
||||
allow a comma-seperated list of optional constructs:
|
||||
doxygen allow doxygen-style block comments (/** /*!)
|
||||
splint allow splint-style lint comments (/*@ ... @*/)
|
||||
";
|
||||
|
||||
my %opts;
|
||||
|
||||
if (!getopts("cho:vC", \%opts)) {
|
||||
print $usage;
|
||||
exit 2;
|
||||
}
|
||||
|
||||
my $check_continuation = $opts{'c'};
|
||||
my $heuristic = $opts{'h'};
|
||||
my $verbose = $opts{'v'};
|
||||
my $ignore_hdr_comment = $opts{'C'};
|
||||
|
||||
my $doxygen_comments = 0;
|
||||
my $splint_comments = 0;
|
||||
|
||||
if (defined($opts{'o'})) {
|
||||
for my $x (split /,/, $opts{'o'}) {
|
||||
if ($x eq "doxygen") {
|
||||
$doxygen_comments = 1;
|
||||
} elsif ($x eq "splint") {
|
||||
$splint_comments = 1;
|
||||
} else {
|
||||
print "jsstyle: unrecognized construct \"$x\"\n";
|
||||
print $usage;
|
||||
exit 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
my ($filename, $line, $prev); # shared globals
|
||||
|
||||
my $fmt;
|
||||
my $hdr_comment_start;
|
||||
|
||||
if ($verbose) {
|
||||
$fmt = "%s: %d: %s\n%s\n";
|
||||
} else {
|
||||
$fmt = "%s: %d: %s\n";
|
||||
}
|
||||
|
||||
if ($doxygen_comments) {
|
||||
# doxygen comments look like "/*!" or "/**"; allow them.
|
||||
$hdr_comment_start = qr/^\s*\/\*[\!\*]?$/;
|
||||
} else {
|
||||
$hdr_comment_start = qr/^\s*\/\*$/;
|
||||
}
|
||||
|
||||
# Note, following must be in single quotes so that \s and \w work right.
|
||||
my $lint_re = qr/\/\*(?:
|
||||
jsl:\w+?|ARGSUSED[0-9]*|NOTREACHED|LINTLIBRARY|VARARGS[0-9]*|
|
||||
CONSTCOND|CONSTANTCOND|CONSTANTCONDITION|EMPTY|
|
||||
FALLTHRU|FALLTHROUGH|LINTED.*?|PRINTFLIKE[0-9]*|
|
||||
PROTOLIB[0-9]*|SCANFLIKE[0-9]*|JSSTYLED.*?
|
||||
)\*\//x;
|
||||
|
||||
my $splint_re = qr/\/\*@.*?@\*\//x;
|
||||
|
||||
my $err_stat = 0; # exit status
|
||||
|
||||
if ($#ARGV >= 0) {
|
||||
foreach my $arg (@ARGV) {
|
||||
my $fh = new IO::File $arg, "r";
|
||||
if (!defined($fh)) {
|
||||
printf "%s: cannot open\n", $arg;
|
||||
} else {
|
||||
&jsstyle($arg, $fh);
|
||||
close $fh;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
&jsstyle("<stdin>", *STDIN);
|
||||
}
|
||||
exit $err_stat;
|
||||
|
||||
my $no_errs = 0; # set for JSSTYLED-protected lines
|
||||
|
||||
sub err($) {
|
||||
my ($error) = @_;
|
||||
unless ($no_errs) {
|
||||
printf $fmt, $filename, $., $error, $line;
|
||||
$err_stat = 1;
|
||||
}
|
||||
}
|
||||
|
||||
sub err_prefix($$) {
|
||||
my ($prevline, $error) = @_;
|
||||
my $out = $prevline."\n".$line;
|
||||
unless ($no_errs) {
|
||||
printf $fmt, $filename, $., $error, $out;
|
||||
$err_stat = 1;
|
||||
}
|
||||
}
|
||||
|
||||
sub err_prev($) {
|
||||
my ($error) = @_;
|
||||
unless ($no_errs) {
|
||||
printf $fmt, $filename, $. - 1, $error, $prev;
|
||||
$err_stat = 1;
|
||||
}
|
||||
}
|
||||
|
||||
sub jsstyle($$) {
|
||||
|
||||
my ($fn, $filehandle) = @_;
|
||||
$filename = $fn; # share it globally
|
||||
|
||||
my $in_cpp = 0;
|
||||
my $next_in_cpp = 0;
|
||||
|
||||
my $in_comment = 0;
|
||||
my $in_header_comment = 0;
|
||||
my $comment_done = 0;
|
||||
my $in_function = 0;
|
||||
my $in_function_header = 0;
|
||||
my $in_declaration = 0;
|
||||
my $note_level = 0;
|
||||
my $nextok = 0;
|
||||
my $nocheck = 0;
|
||||
|
||||
my $in_string = 0;
|
||||
|
||||
my ($okmsg, $comment_prefix);
|
||||
|
||||
$line = '';
|
||||
$prev = '';
|
||||
reset_indent();
|
||||
|
||||
line: while (<$filehandle>) {
|
||||
s/\r?\n$//; # strip return and newline
|
||||
|
||||
# save the original line, then remove all text from within
|
||||
# double or single quotes, we do not want to check such text.
|
||||
|
||||
$line = $_;
|
||||
|
||||
#
|
||||
# C allows strings to be continued with a backslash at the end of
|
||||
# the line. We translate that into a quoted string on the previous
|
||||
# line followed by an initial quote on the next line.
|
||||
#
|
||||
# (we assume that no-one will use backslash-continuation with character
|
||||
# constants)
|
||||
#
|
||||
$_ = '"' . $_ if ($in_string && !$nocheck && !$in_comment);
|
||||
|
||||
#
|
||||
# normal strings and characters
|
||||
#
|
||||
s/'([^\\']|\\.)*'/\'\'/g;
|
||||
s/"([^\\"]|\\.)*"/\"\"/g;
|
||||
|
||||
#
|
||||
# detect string continuation
|
||||
#
|
||||
if ($nocheck || $in_comment) {
|
||||
$in_string = 0;
|
||||
} else {
|
||||
#
|
||||
# Now that all full strings are replaced with "", we check
|
||||
# for unfinished strings continuing onto the next line.
|
||||
#
|
||||
$in_string =
|
||||
(s/([^"](?:"")*)"([^\\"]|\\.)*\\$/$1""/ ||
|
||||
s/^("")*"([^\\"]|\\.)*\\$/""/);
|
||||
}
|
||||
|
||||
#
|
||||
# figure out if we are in a cpp directive
|
||||
#
|
||||
$in_cpp = $next_in_cpp || /^\s*#/; # continued or started
|
||||
$next_in_cpp = $in_cpp && /\\$/; # only if continued
|
||||
|
||||
# strip off trailing backslashes, which appear in long macros
|
||||
s/\s*\\$//;
|
||||
|
||||
# an /* END JSSTYLED */ comment ends a no-check block.
|
||||
if ($nocheck) {
|
||||
if (/\/\* *END *JSSTYLED *\*\//) {
|
||||
$nocheck = 0;
|
||||
} else {
|
||||
reset_indent();
|
||||
next line;
|
||||
}
|
||||
}
|
||||
|
||||
# a /*JSSTYLED*/ comment indicates that the next line is ok.
|
||||
if ($nextok) {
|
||||
if ($okmsg) {
|
||||
err($okmsg);
|
||||
}
|
||||
$nextok = 0;
|
||||
$okmsg = 0;
|
||||
if (/\/\* *JSSTYLED.*\*\//) {
|
||||
/^.*\/\* *JSSTYLED *(.*) *\*\/.*$/;
|
||||
$okmsg = $1;
|
||||
$nextok = 1;
|
||||
}
|
||||
$no_errs = 1;
|
||||
} elsif ($no_errs) {
|
||||
$no_errs = 0;
|
||||
}
|
||||
|
||||
# check length of line.
|
||||
# first, a quick check to see if there is any chance of being too long.
|
||||
if (($line =~ tr/\t/\t/) * 7 + length($line) > 80) {
|
||||
# yes, there is a chance.
|
||||
# replace tabs with spaces and check again.
|
||||
my $eline = $line;
|
||||
1 while $eline =~
|
||||
s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e;
|
||||
if (length($eline) > 80) {
|
||||
err("line > 80 characters");
|
||||
}
|
||||
}
|
||||
|
||||
# ignore NOTE(...) annotations (assumes NOTE is on lines by itself).
|
||||
if ($note_level || /\b_?NOTE\s*\(/) { # if in NOTE or this is NOTE
|
||||
s/[^()]//g; # eliminate all non-parens
|
||||
$note_level += s/\(//g - length; # update paren nest level
|
||||
next;
|
||||
}
|
||||
|
||||
# a /* BEGIN JSSTYLED */ comment starts a no-check block.
|
||||
if (/\/\* *BEGIN *JSSTYLED *\*\//) {
|
||||
$nocheck = 1;
|
||||
}
|
||||
|
||||
# a /*JSSTYLED*/ comment indicates that the next line is ok.
|
||||
if (/\/\* *JSSTYLED.*\*\//) {
|
||||
/^.*\/\* *JSSTYLED *(.*) *\*\/.*$/;
|
||||
$okmsg = $1;
|
||||
$nextok = 1;
|
||||
}
|
||||
if (/\/\/ *JSSTYLED/) {
|
||||
/^.*\/\/ *JSSTYLED *(.*)$/;
|
||||
$okmsg = $1;
|
||||
$nextok = 1;
|
||||
}
|
||||
|
||||
# universal checks; apply to everything
|
||||
if (/\t +\t/) {
|
||||
err("spaces between tabs");
|
||||
}
|
||||
if (/ \t+ /) {
|
||||
err("tabs between spaces");
|
||||
}
|
||||
if (/\s$/) {
|
||||
err("space or tab at end of line");
|
||||
}
|
||||
if (/[^ \t(]\/\*/ && !/\w\(\/\*.*\*\/\);/) {
|
||||
err("comment preceded by non-blank");
|
||||
}
|
||||
|
||||
# is this the beginning or ending of a function?
|
||||
# (not if "struct foo\n{\n")
|
||||
if (/^{$/ && $prev =~ /\)\s*(const\s*)?(\/\*.*\*\/\s*)?\\?$/) {
|
||||
$in_function = 1;
|
||||
$in_declaration = 1;
|
||||
$in_function_header = 0;
|
||||
$prev = $line;
|
||||
next line;
|
||||
}
|
||||
if (/^}\s*(\/\*.*\*\/\s*)*$/) {
|
||||
if ($prev =~ /^\s*return\s*;/) {
|
||||
err_prev("unneeded return at end of function");
|
||||
}
|
||||
$in_function = 0;
|
||||
reset_indent(); # we don't check between functions
|
||||
$prev = $line;
|
||||
next line;
|
||||
}
|
||||
if (/^\w*\($/) {
|
||||
$in_function_header = 1;
|
||||
}
|
||||
|
||||
# a blank line terminates the declarations within a function.
|
||||
# XXX - but still a problem in sub-blocks.
|
||||
if ($in_declaration && /^$/) {
|
||||
$in_declaration = 0;
|
||||
}
|
||||
|
||||
if ($comment_done) {
|
||||
$in_comment = 0;
|
||||
$in_header_comment = 0;
|
||||
$comment_done = 0;
|
||||
}
|
||||
# does this looks like the start of a block comment?
|
||||
if (/$hdr_comment_start/) {
|
||||
if (!/^\t*\/\*/) {
|
||||
err("block comment not indented by tabs");
|
||||
}
|
||||
$in_comment = 1;
|
||||
/^(\s*)\//;
|
||||
$comment_prefix = $1;
|
||||
if ($comment_prefix eq "") {
|
||||
$in_header_comment = 1;
|
||||
}
|
||||
$prev = $line;
|
||||
next line;
|
||||
}
|
||||
# are we still in the block comment?
|
||||
if ($in_comment) {
|
||||
if (/^$comment_prefix \*\/$/) {
|
||||
$comment_done = 1;
|
||||
} elsif (/\*\//) {
|
||||
$comment_done = 1;
|
||||
err("improper block comment close")
|
||||
unless ($ignore_hdr_comment && $in_header_comment);
|
||||
} elsif (!/^$comment_prefix \*[ \t]/ &&
|
||||
!/^$comment_prefix \*$/) {
|
||||
err("improper block comment")
|
||||
unless ($ignore_hdr_comment && $in_header_comment);
|
||||
}
|
||||
}
|
||||
|
||||
if ($in_header_comment && $ignore_hdr_comment) {
|
||||
$prev = $line;
|
||||
next line;
|
||||
}
|
||||
|
||||
# check for errors that might occur in comments and in code.
|
||||
|
||||
# allow spaces to be used to draw pictures in header comments.
|
||||
#if (/[^ ] / && !/".* .*"/ && !$in_header_comment) {
|
||||
# err("spaces instead of tabs");
|
||||
#}
|
||||
#if (/^ / && !/^ \*[ \t\/]/ && !/^ \*$/ &&
|
||||
# (!/^ \w/ || $in_function != 0)) {
|
||||
# err("indent by spaces instead of tabs");
|
||||
#}
|
||||
if (/^ {2,}/ && !/^ [^ ]/) {
|
||||
err("indent by spaces instead of tabs");
|
||||
}
|
||||
if (/^\t+ [^ \t\*]/ || /^\t+ \S/ || /^\t+ \S/) {
|
||||
err("continuation line not indented by 4 spaces");
|
||||
}
|
||||
|
||||
if (/^\s*\/\*./ && !/^\s*\/\*.*\*\// && !/$hdr_comment_start/) {
|
||||
err("improper first line of block comment");
|
||||
}
|
||||
|
||||
if ($in_comment) { # still in comment, don't do further checks
|
||||
$prev = $line;
|
||||
next line;
|
||||
}
|
||||
|
||||
if ((/[^(]\/\*\S/ || /^\/\*\S/) &&
|
||||
!(/$lint_re/ || ($splint_comments && /$splint_re/))) {
|
||||
err("missing blank after open comment");
|
||||
}
|
||||
if (/\S\*\/[^)]|\S\*\/$/ &&
|
||||
!(/$lint_re/ || ($splint_comments && /$splint_re/))) {
|
||||
err("missing blank before close comment");
|
||||
}
|
||||
if (/\/\/\S/) { # C++ comments
|
||||
err("missing blank after start comment");
|
||||
}
|
||||
# check for unterminated single line comments, but allow them when
|
||||
# they are used to comment out the argument list of a function
|
||||
# declaration.
|
||||
if (/\S.*\/\*/ && !/\S.*\/\*.*\*\// && !/\(\/\*/) {
|
||||
err("unterminated single line comment");
|
||||
}
|
||||
|
||||
if (/^(#else|#endif|#include)(.*)$/) {
|
||||
$prev = $line;
|
||||
next line;
|
||||
}
|
||||
|
||||
#
|
||||
# delete any comments and check everything else. Note that
|
||||
# ".*?" is a non-greedy match, so that we don't get confused by
|
||||
# multiple comments on the same line.
|
||||
#
|
||||
s/\/\*.*?\*\///g;
|
||||
s/\/\/.*$//; # C++ comments
|
||||
|
||||
# delete any trailing whitespace; we have already checked for that.
|
||||
s/\s*$//;
|
||||
|
||||
# following checks do not apply to text in comments.
|
||||
if (/"/) {
|
||||
err("literal string using double-quote instead of single");
|
||||
}
|
||||
|
||||
if (/[^=!<>\s][!<>=]=/ || /[^<>!=][!<>=]==?[^\s,=]/ ||
|
||||
(/[^->]>[^,=>\s]/ && !/[^->]>$/) ||
|
||||
(/[^<]<[^,=<\s]/ && !/[^<]<$/) ||
|
||||
/[^<\s]<[^<]/ || /[^->\s]>[^>]/) {
|
||||
err("missing space around relational operator");
|
||||
}
|
||||
if (/\S>>=/ || /\S<<=/ || />>=\S/ || /<<=\S/ || /\S[-+*\/&|^%]=/ ||
|
||||
(/[^-+*\/&|^%!<>=\s]=[^=]/ && !/[^-+*\/&|^%!<>=\s]=$/) ||
|
||||
(/[^!<>=]=[^=\s]/ && !/[^!<>=]=$/)) {
|
||||
# XXX - should only check this for C++ code
|
||||
# XXX - there are probably other forms that should be allowed
|
||||
if (!/\soperator=/) {
|
||||
err("missing space around assignment operator");
|
||||
}
|
||||
}
|
||||
if (/[,;]\S/ && !/\bfor \(;;\)/) {
|
||||
err("comma or semicolon followed by non-blank");
|
||||
}
|
||||
# allow "for" statements to have empty "while" clauses
|
||||
if (/\s[,;]/ && !/^[\t]+;$/ && !/^\s*for \([^;]*; ;[^;]*\)/) {
|
||||
err("comma or semicolon preceded by blank");
|
||||
}
|
||||
if (/^\s*(&&|\|\|)/) {
|
||||
err("improper boolean continuation");
|
||||
}
|
||||
if (/\S *(&&|\|\|)/ || /(&&|\|\|) *\S/) {
|
||||
err("more than one space around boolean operator");
|
||||
}
|
||||
if (/\b(delete|typeof|instanceOf|throw|with|catch|new|function|in|for|if|while|switch|return|case)\(/) {
|
||||
err("missing space between keyword and paren");
|
||||
}
|
||||
if (/(\b(catch|for|if|with|while|switch|return)\b.*){2,}/) {
|
||||
# multiple "case" and "sizeof" allowed
|
||||
err("more than one keyword on line");
|
||||
}
|
||||
if (/\b(delete|typeof|instanceOf|with|throw|catch|new|function|in|for|if|while|switch|return|case)\s\s+\(/ &&
|
||||
!/^#if\s+\(/) {
|
||||
err("extra space between keyword and paren");
|
||||
}
|
||||
# try to detect "func (x)" but not "if (x)" or
|
||||
# "#define foo (x)" or "int (*func)();"
|
||||
if (/\w\s\(/) {
|
||||
my $s = $_;
|
||||
# strip off all keywords on the line
|
||||
s/\b(delete|typeof|instanceOf|throw|with|catch|new|function|in|for|if|while|switch|return|case)\s\(/XXX(/g;
|
||||
s/#elif\s\(/XXX(/g;
|
||||
s/^#define\s+\w+\s+\(/XXX(/;
|
||||
# do not match things like "void (*f)();"
|
||||
# or "typedef void (func_t)();"
|
||||
s/\w\s\(+\*/XXX(*/g;
|
||||
s/\b(void)\s+\(+/XXX(/og;
|
||||
if (/\w\s\(/) {
|
||||
err("extra space between function name and left paren");
|
||||
}
|
||||
$_ = $s;
|
||||
}
|
||||
|
||||
if (/^\s*return\W[^;]*;/ && !/^\s*return\s*\(.*\);/) {
|
||||
err("unparenthesized return expression");
|
||||
}
|
||||
if (/\btypeof\b/ && !/\btypeof\s*\(.*\)/) {
|
||||
err("unparenthesized typeof expression");
|
||||
}
|
||||
if (/\(\s/) {
|
||||
err("whitespace after left paren");
|
||||
}
|
||||
# allow "for" statements to have empty "continue" clauses
|
||||
if (/\s\)/ && !/^\s*for \([^;]*;[^;]*; \)/) {
|
||||
err("whitespace before right paren");
|
||||
}
|
||||
if (/^\s*\(void\)[^ ]/) {
|
||||
err("missing space after (void) cast");
|
||||
}
|
||||
if (/\S{/ && !/({|\(){/) {
|
||||
err("missing space before left brace");
|
||||
}
|
||||
if ($in_function && /^\s+{/ &&
|
||||
($prev =~ /\)\s*$/ || $prev =~ /\bstruct\s+\w+$/)) {
|
||||
err("left brace starting a line");
|
||||
}
|
||||
if (/}(else|while)/) {
|
||||
err("missing space after right brace");
|
||||
}
|
||||
if (/}\s\s+(else|while)/) {
|
||||
err("extra space after right brace");
|
||||
}
|
||||
if (/^\s+#/) {
|
||||
err("preprocessor statement not in column 1");
|
||||
}
|
||||
if (/^#\s/) {
|
||||
err("blank after preprocessor #");
|
||||
}
|
||||
|
||||
#
|
||||
# We completely ignore, for purposes of indentation:
|
||||
# * lines outside of functions
|
||||
# * preprocessor lines
|
||||
#
|
||||
if ($check_continuation && $in_function && !$in_cpp) {
|
||||
process_indent($_);
|
||||
}
|
||||
|
||||
if ($heuristic) {
|
||||
# cannot check this everywhere due to "struct {\n...\n} foo;"
|
||||
if ($in_function && !$in_declaration &&
|
||||
/}./ && !/}\s+=/ && !/{.*}[;,]$/ && !/}(\s|)*$/ &&
|
||||
!/} (else|while)/ && !/}}/) {
|
||||
err("possible bad text following right brace");
|
||||
}
|
||||
# cannot check this because sub-blocks in
|
||||
# the middle of code are ok
|
||||
if ($in_function && /^\s+{/) {
|
||||
err("possible left brace starting a line");
|
||||
}
|
||||
}
|
||||
if (/^\s*else\W/) {
|
||||
if ($prev =~ /^\s*}$/) {
|
||||
err_prefix($prev,
|
||||
"else and right brace should be on same line");
|
||||
}
|
||||
}
|
||||
$prev = $line;
|
||||
}
|
||||
|
||||
if ($prev eq "") {
|
||||
err("last line in file is blank");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#
|
||||
# Continuation-line checking
|
||||
#
|
||||
# The rest of this file contains the code for the continuation checking
|
||||
# engine. It's a pretty simple state machine which tracks the expression
|
||||
# depth (unmatched '('s and '['s).
|
||||
#
|
||||
# Keep in mind that the argument to process_indent() has already been heavily
|
||||
# processed; all comments have been replaced by control-A, and the contents of
|
||||
# strings and character constants have been elided.
|
||||
#
|
||||
|
||||
my $cont_in; # currently inside of a continuation
|
||||
my $cont_off; # skipping an initializer or definition
|
||||
my $cont_noerr; # suppress cascading errors
|
||||
my $cont_start; # the line being continued
|
||||
my $cont_base; # the base indentation
|
||||
my $cont_first; # this is the first line of a statement
|
||||
my $cont_multiseg; # this continuation has multiple segments
|
||||
|
||||
my $cont_special; # this is a C statement (if, for, etc.)
|
||||
my $cont_macro; # this is a macro
|
||||
my $cont_case; # this is a multi-line case
|
||||
|
||||
my @cont_paren; # the stack of unmatched ( and [s we've seen
|
||||
|
||||
sub
|
||||
reset_indent()
|
||||
{
|
||||
$cont_in = 0;
|
||||
$cont_off = 0;
|
||||
}
|
||||
|
||||
sub
|
||||
delabel($)
|
||||
{
|
||||
#
|
||||
# replace labels with tabs. Note that there may be multiple
|
||||
# labels on a line.
|
||||
#
|
||||
local $_ = $_[0];
|
||||
|
||||
while (/^(\t*)( *(?:(?:\w+\s*)|(?:case\b[^:]*)): *)(.*)$/) {
|
||||
my ($pre_tabs, $label, $rest) = ($1, $2, $3);
|
||||
$_ = $pre_tabs;
|
||||
while ($label =~ s/^([^\t]*)(\t+)//) {
|
||||
$_ .= "\t" x (length($2) + length($1) / 8);
|
||||
}
|
||||
$_ .= ("\t" x (length($label) / 8)).$rest;
|
||||
}
|
||||
|
||||
return ($_);
|
||||
}
|
||||
|
||||
sub
|
||||
process_indent($)
|
||||
{
|
||||
require strict;
|
||||
local $_ = $_[0]; # preserve the global $_
|
||||
|
||||
s///g; # No comments
|
||||
s/\s+$//; # Strip trailing whitespace
|
||||
|
||||
return if (/^$/); # skip empty lines
|
||||
|
||||
# regexps used below; keywords taking (), macros, and continued cases
|
||||
my $special = '(?:(?:\}\s*)?else\s+)?(?:if|for|while|switch)\b';
|
||||
my $macro = '[A-Z_][A-Z_0-9]*\(';
|
||||
my $case = 'case\b[^:]*$';
|
||||
|
||||
# skip over enumerations, array definitions, initializers, etc.
|
||||
if ($cont_off <= 0 && !/^\s*$special/ &&
|
||||
(/(?:(?:\b(?:enum|struct|union)\s*[^\{]*)|(?:\s+=\s*)){/ ||
|
||||
(/^\s*{/ && $prev =~ /=\s*(?:\/\*.*\*\/\s*)*$/))) {
|
||||
$cont_in = 0;
|
||||
$cont_off = tr/{/{/ - tr/}/}/;
|
||||
return;
|
||||
}
|
||||
if ($cont_off) {
|
||||
$cont_off += tr/{/{/ - tr/}/}/;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$cont_in) {
|
||||
$cont_start = $line;
|
||||
|
||||
if (/^\t* /) {
|
||||
err("non-continuation indented 4 spaces");
|
||||
$cont_noerr = 1; # stop reporting
|
||||
}
|
||||
$_ = delabel($_); # replace labels with tabs
|
||||
|
||||
# check if the statement is complete
|
||||
return if (/^\s*\}?$/);
|
||||
return if (/^\s*\}?\s*else\s*\{?$/);
|
||||
return if (/^\s*do\s*\{?$/);
|
||||
return if (/{$/);
|
||||
return if (/}[,;]?$/);
|
||||
|
||||
# Allow macros on their own lines
|
||||
return if (/^\s*[A-Z_][A-Z_0-9]*$/);
|
||||
|
||||
# cases we don't deal with, generally non-kosher
|
||||
if (/{/) {
|
||||
err("stuff after {");
|
||||
return;
|
||||
}
|
||||
|
||||
# Get the base line, and set up the state machine
|
||||
/^(\t*)/;
|
||||
$cont_base = $1;
|
||||
$cont_in = 1;
|
||||
@cont_paren = ();
|
||||
$cont_first = 1;
|
||||
$cont_multiseg = 0;
|
||||
|
||||
# certain things need special processing
|
||||
$cont_special = /^\s*$special/? 1 : 0;
|
||||
$cont_macro = /^\s*$macro/? 1 : 0;
|
||||
$cont_case = /^\s*$case/? 1 : 0;
|
||||
} else {
|
||||
$cont_first = 0;
|
||||
|
||||
# Strings may be pulled back to an earlier (half-)tabstop
|
||||
unless ($cont_noerr || /^$cont_base / ||
|
||||
(/^\t*(?: )?(?:gettext\()?\"/ && !/^$cont_base\t/)) {
|
||||
err_prefix($cont_start,
|
||||
"continuation should be indented 4 spaces");
|
||||
}
|
||||
}
|
||||
|
||||
my $rest = $_; # keeps the remainder of the line
|
||||
|
||||
#
|
||||
# The split matches 0 characters, so that each 'special' character
|
||||
# is processed separately. Parens and brackets are pushed and
|
||||
# popped off the @cont_paren stack. For normal processing, we wait
|
||||
# until a ; or { terminates the statement. "special" processing
|
||||
# (if/for/while/switch) is allowed to stop when the stack empties,
|
||||
# as is macro processing. Case statements are terminated with a :
|
||||
# and an empty paren stack.
|
||||
#
|
||||
foreach $_ (split /[^\(\)\[\]\{\}\;\:]*/) {
|
||||
next if (length($_) == 0);
|
||||
|
||||
# rest contains the remainder of the line
|
||||
my $rxp = "[^\Q$_\E]*\Q$_\E";
|
||||
$rest =~ s/^$rxp//;
|
||||
|
||||
if (/\(/ || /\[/) {
|
||||
push @cont_paren, $_;
|
||||
} elsif (/\)/ || /\]/) {
|
||||
my $cur = $_;
|
||||
tr/\)\]/\(\[/;
|
||||
|
||||
my $old = (pop @cont_paren);
|
||||
if (!defined($old)) {
|
||||
err("unexpected '$cur'");
|
||||
$cont_in = 0;
|
||||
last;
|
||||
} elsif ($old ne $_) {
|
||||
err("'$cur' mismatched with '$old'");
|
||||
$cont_in = 0;
|
||||
last;
|
||||
}
|
||||
|
||||
#
|
||||
# If the stack is now empty, do special processing
|
||||
# for if/for/while/switch and macro statements.
|
||||
#
|
||||
next if (@cont_paren != 0);
|
||||
if ($cont_special) {
|
||||
if ($rest =~ /^\s*{?$/) {
|
||||
$cont_in = 0;
|
||||
last;
|
||||
}
|
||||
if ($rest =~ /^\s*;$/) {
|
||||
err("empty if/for/while body ".
|
||||
"not on its own line");
|
||||
$cont_in = 0;
|
||||
last;
|
||||
}
|
||||
if (!$cont_first && $cont_multiseg == 1) {
|
||||
err_prefix($cont_start,
|
||||
"multiple statements continued ".
|
||||
"over multiple lines");
|
||||
$cont_multiseg = 2;
|
||||
} elsif ($cont_multiseg == 0) {
|
||||
$cont_multiseg = 1;
|
||||
}
|
||||
# We've finished this section, start
|
||||
# processing the next.
|
||||
goto section_ended;
|
||||
}
|
||||
if ($cont_macro) {
|
||||
if ($rest =~ /^$/) {
|
||||
$cont_in = 0;
|
||||
last;
|
||||
}
|
||||
}
|
||||
} elsif (/\;/) {
|
||||
if ($cont_case) {
|
||||
err("unexpected ;");
|
||||
} elsif (!$cont_special) {
|
||||
err("unexpected ;") if (@cont_paren != 0);
|
||||
if (!$cont_first && $cont_multiseg == 1) {
|
||||
err_prefix($cont_start,
|
||||
"multiple statements continued ".
|
||||
"over multiple lines");
|
||||
$cont_multiseg = 2;
|
||||
} elsif ($cont_multiseg == 0) {
|
||||
$cont_multiseg = 1;
|
||||
}
|
||||
if ($rest =~ /^$/) {
|
||||
$cont_in = 0;
|
||||
last;
|
||||
}
|
||||
if ($rest =~ /^\s*special/) {
|
||||
err("if/for/while/switch not started ".
|
||||
"on its own line");
|
||||
}
|
||||
goto section_ended;
|
||||
}
|
||||
} elsif (/\{/) {
|
||||
err("{ while in parens/brackets") if (@cont_paren != 0);
|
||||
err("stuff after {") if ($rest =~ /[^\s}]/);
|
||||
$cont_in = 0;
|
||||
last;
|
||||
} elsif (/\}/) {
|
||||
err("} while in parens/brackets") if (@cont_paren != 0);
|
||||
if (!$cont_special && $rest !~ /^\s*(while|else)\b/) {
|
||||
if ($rest =~ /^$/) {
|
||||
err("unexpected }");
|
||||
} else {
|
||||
err("stuff after }");
|
||||
}
|
||||
$cont_in = 0;
|
||||
last;
|
||||
}
|
||||
} elsif (/\:/ && $cont_case && @cont_paren == 0) {
|
||||
err("stuff after multi-line case") if ($rest !~ /$^/);
|
||||
$cont_in = 0;
|
||||
last;
|
||||
}
|
||||
next;
|
||||
section_ended:
|
||||
# End of a statement or if/while/for loop. Reset
|
||||
# cont_special and cont_macro based on the rest of the
|
||||
# line.
|
||||
$cont_special = ($rest =~ /^\s*$special/)? 1 : 0;
|
||||
$cont_macro = ($rest =~ /^\s*$macro/)? 1 : 0;
|
||||
$cont_case = 0;
|
||||
next;
|
||||
}
|
||||
$cont_noerr = 0 if (!$cont_in);
|
||||
}
|
||||
Reference in New Issue
Block a user