mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-05 07:18:39 +09:00
import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo
This commit is contained in:
commit
dcd9973243
150858 changed files with 23884658 additions and 0 deletions
657
modules/libpref/prefread.cpp
Normal file
657
modules/libpref/prefread.cpp
Normal file
|
|
@ -0,0 +1,657 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include "prefread.h"
|
||||
#include "nsString.h"
|
||||
#include "nsUTF8Utils.h"
|
||||
|
||||
#ifdef TEST_PREFREAD
|
||||
#include <stdio.h>
|
||||
#define NS_WARNING(_s) printf(">>> " _s "!\n")
|
||||
#define NS_NOTREACHED(_s) NS_WARNING(_s)
|
||||
#else
|
||||
#include "nsDebug.h" // for NS_WARNING
|
||||
#endif
|
||||
|
||||
/* pref parser states */
|
||||
enum {
|
||||
PREF_PARSE_INIT,
|
||||
PREF_PARSE_MATCH_STRING,
|
||||
PREF_PARSE_UNTIL_NAME,
|
||||
PREF_PARSE_QUOTED_STRING,
|
||||
PREF_PARSE_UNTIL_COMMA,
|
||||
PREF_PARSE_UNTIL_VALUE,
|
||||
PREF_PARSE_INT_VALUE,
|
||||
PREF_PARSE_COMMENT_MAYBE_START,
|
||||
PREF_PARSE_COMMENT_BLOCK,
|
||||
PREF_PARSE_COMMENT_BLOCK_MAYBE_END,
|
||||
PREF_PARSE_ESC_SEQUENCE,
|
||||
PREF_PARSE_HEX_ESCAPE,
|
||||
PREF_PARSE_UTF16_LOW_SURROGATE,
|
||||
PREF_PARSE_UNTIL_OPEN_PAREN,
|
||||
PREF_PARSE_UNTIL_CLOSE_PAREN,
|
||||
PREF_PARSE_UNTIL_SEMICOLON,
|
||||
PREF_PARSE_UNTIL_EOL
|
||||
};
|
||||
|
||||
#define UTF16_ESC_NUM_DIGITS 4
|
||||
#define HEX_ESC_NUM_DIGITS 2
|
||||
#define BITS_PER_HEX_DIGIT 4
|
||||
|
||||
static const char kUserPref[] = "user_pref";
|
||||
static const char kPref[] = "pref";
|
||||
static const char kPrefSticky[] = "sticky_pref";
|
||||
static const char kTrue[] = "true";
|
||||
static const char kFalse[] = "false";
|
||||
|
||||
/**
|
||||
* pref_GrowBuf
|
||||
*
|
||||
* this function will increase the size of the buffer owned
|
||||
* by the given pref parse state. We currently use a simple
|
||||
* doubling algorithm, but the only hard requirement is that
|
||||
* it increase the buffer by at least the size of the ps->esctmp
|
||||
* buffer used for escape processing (currently 6 bytes).
|
||||
*
|
||||
* this buffer is used to store partial pref lines. it is
|
||||
* freed when the parse state is destroyed.
|
||||
*
|
||||
* @param ps
|
||||
* parse state instance
|
||||
*
|
||||
* this function updates all pointers that reference an
|
||||
* address within lb since realloc may relocate the buffer.
|
||||
*
|
||||
* @return false if insufficient memory.
|
||||
*/
|
||||
static bool
|
||||
pref_GrowBuf(PrefParseState *ps)
|
||||
{
|
||||
int bufLen, curPos, valPos;
|
||||
|
||||
bufLen = ps->lbend - ps->lb;
|
||||
curPos = ps->lbcur - ps->lb;
|
||||
valPos = ps->vb - ps->lb;
|
||||
|
||||
if (bufLen == 0)
|
||||
bufLen = 128; /* default buffer size */
|
||||
else
|
||||
bufLen <<= 1; /* double buffer size */
|
||||
|
||||
#ifdef TEST_PREFREAD
|
||||
fprintf(stderr, ">>> realloc(%d)\n", bufLen);
|
||||
#endif
|
||||
|
||||
ps->lb = (char*) realloc(ps->lb, bufLen);
|
||||
if (!ps->lb)
|
||||
return false;
|
||||
|
||||
ps->lbcur = ps->lb + curPos;
|
||||
ps->lbend = ps->lb + bufLen;
|
||||
ps->vb = ps->lb + valPos;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Report an error or a warning. If not specified, just dump to stderr.
|
||||
*/
|
||||
static void
|
||||
pref_ReportParseProblem(PrefParseState& ps, const char* aMessage, int aLine, bool aError)
|
||||
{
|
||||
if (ps.reporter) {
|
||||
ps.reporter(aMessage, aLine, aError);
|
||||
} else {
|
||||
printf_stderr("**** Preference parsing %s (line %d) = %s **\n",
|
||||
(aError ? "error" : "warning"), aLine, aMessage);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* pref_DoCallback
|
||||
*
|
||||
* this function is called when a complete pref name-value pair has
|
||||
* been extracted from the input data.
|
||||
*
|
||||
* @param ps
|
||||
* parse state instance
|
||||
*
|
||||
* @return false to indicate a fatal error.
|
||||
*/
|
||||
static bool
|
||||
pref_DoCallback(PrefParseState *ps)
|
||||
{
|
||||
PrefValue value;
|
||||
|
||||
switch (ps->vtype) {
|
||||
case PrefType::String:
|
||||
value.stringVal = ps->vb;
|
||||
break;
|
||||
case PrefType::Int:
|
||||
if ((ps->vb[0] == '-' || ps->vb[0] == '+') && ps->vb[1] == '\0') {
|
||||
pref_ReportParseProblem(*ps, "invalid integer value", 0, true);
|
||||
NS_WARNING("malformed integer value");
|
||||
return false;
|
||||
}
|
||||
value.intVal = atoi(ps->vb);
|
||||
break;
|
||||
case PrefType::Bool:
|
||||
value.boolVal = (ps->vb == kTrue);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
(*ps->reader)(ps->closure, ps->lb, value, ps->vtype, ps->fdefault,
|
||||
ps->fstickydefault);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
PREF_InitParseState(PrefParseState *ps, PrefReader reader,
|
||||
PrefParseErrorReporter reporter, void *closure)
|
||||
{
|
||||
memset(ps, 0, sizeof(*ps));
|
||||
ps->reader = reader;
|
||||
ps->closure = closure;
|
||||
ps->reporter = reporter;
|
||||
}
|
||||
|
||||
void
|
||||
PREF_FinalizeParseState(PrefParseState *ps)
|
||||
{
|
||||
if (ps->lb)
|
||||
free(ps->lb);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pseudo-BNF
|
||||
* ----------
|
||||
* function = LJUNK function-name JUNK function-args
|
||||
* function-name = "user_pref" | "pref" | "sticky_pref"
|
||||
* function-args = "(" JUNK pref-name JUNK "," JUNK pref-value JUNK ")" JUNK ";"
|
||||
* pref-name = quoted-string
|
||||
* pref-value = quoted-string | "true" | "false" | integer-value
|
||||
* JUNK = *(WS | comment-block | comment-line)
|
||||
* LJUNK = *(WS | comment-block | comment-line | bcomment-line)
|
||||
* WS = SP | HT | LF | VT | FF | CR
|
||||
* SP = <US-ASCII SP, space (32)>
|
||||
* HT = <US-ASCII HT, horizontal-tab (9)>
|
||||
* LF = <US-ASCII LF, linefeed (10)>
|
||||
* VT = <US-ASCII HT, vertical-tab (11)>
|
||||
* FF = <US-ASCII FF, form-feed (12)>
|
||||
* CR = <US-ASCII CR, carriage return (13)>
|
||||
* comment-block = <C/C++ style comment block>
|
||||
* comment-line = <C++ style comment line>
|
||||
* bcomment-line = <bourne-shell style comment line>
|
||||
*/
|
||||
bool
|
||||
PREF_ParseBuf(PrefParseState *ps, const char *buf, int bufLen)
|
||||
{
|
||||
const char *end;
|
||||
char c;
|
||||
char udigit;
|
||||
int state;
|
||||
|
||||
// The line number is currently only used for the error/warning reporting.
|
||||
int lineNum = 0;
|
||||
|
||||
state = ps->state;
|
||||
for (end = buf + bufLen; buf != end; ++buf) {
|
||||
c = *buf;
|
||||
if (c == '\r' || c == '\n' || c == 0x1A) {
|
||||
lineNum ++;
|
||||
}
|
||||
|
||||
switch (state) {
|
||||
/* initial state */
|
||||
case PREF_PARSE_INIT:
|
||||
if (ps->lbcur != ps->lb) { /* reset state */
|
||||
ps->lbcur = ps->lb;
|
||||
ps->vb = nullptr;
|
||||
ps->vtype = PrefType::Invalid;
|
||||
ps->fdefault = false;
|
||||
ps->fstickydefault = false;
|
||||
}
|
||||
switch (c) {
|
||||
case '/': /* begin comment block or line? */
|
||||
state = PREF_PARSE_COMMENT_MAYBE_START;
|
||||
break;
|
||||
case '#': /* accept shell style comments */
|
||||
state = PREF_PARSE_UNTIL_EOL;
|
||||
break;
|
||||
case 'u': /* indicating user_pref */
|
||||
case 's': /* indicating sticky_pref */
|
||||
case 'p': /* indicating pref */
|
||||
if (c == 'u') {
|
||||
ps->smatch = kUserPref;
|
||||
} else if (c == 's') {
|
||||
ps->smatch = kPrefSticky;
|
||||
} else {
|
||||
ps->smatch = kPref;
|
||||
}
|
||||
ps->sindex = 1;
|
||||
ps->nextstate = PREF_PARSE_UNTIL_OPEN_PAREN;
|
||||
state = PREF_PARSE_MATCH_STRING;
|
||||
break;
|
||||
/* else skip char */
|
||||
}
|
||||
break;
|
||||
|
||||
/* string matching */
|
||||
case PREF_PARSE_MATCH_STRING:
|
||||
if (c == ps->smatch[ps->sindex++]) {
|
||||
/* if we've matched all characters, then move to next state. */
|
||||
if (ps->smatch[ps->sindex] == '\0') {
|
||||
state = ps->nextstate;
|
||||
ps->nextstate = PREF_PARSE_INIT; /* reset next state */
|
||||
}
|
||||
/* else wait for next char */
|
||||
}
|
||||
else {
|
||||
pref_ReportParseProblem(*ps, "non-matching string", lineNum, true);
|
||||
NS_WARNING("malformed pref file");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
/* quoted string parsing */
|
||||
case PREF_PARSE_QUOTED_STRING:
|
||||
/* we assume that the initial quote has already been consumed */
|
||||
if (ps->lbcur == ps->lbend && !pref_GrowBuf(ps))
|
||||
return false; /* out of memory */
|
||||
if (c == '\\')
|
||||
state = PREF_PARSE_ESC_SEQUENCE;
|
||||
else if (c == ps->quotechar) {
|
||||
*ps->lbcur++ = '\0';
|
||||
state = ps->nextstate;
|
||||
ps->nextstate = PREF_PARSE_INIT; /* reset next state */
|
||||
}
|
||||
else
|
||||
*ps->lbcur++ = c;
|
||||
break;
|
||||
|
||||
/* name parsing */
|
||||
case PREF_PARSE_UNTIL_NAME:
|
||||
if (c == '\"' || c == '\'') {
|
||||
ps->fdefault = (ps->smatch == kPref || ps->smatch == kPrefSticky);
|
||||
ps->fstickydefault = (ps->smatch == kPrefSticky);
|
||||
ps->quotechar = c;
|
||||
ps->nextstate = PREF_PARSE_UNTIL_COMMA; /* return here when done */
|
||||
state = PREF_PARSE_QUOTED_STRING;
|
||||
}
|
||||
else if (c == '/') { /* allow embedded comment */
|
||||
ps->nextstate = state; /* return here when done with comment */
|
||||
state = PREF_PARSE_COMMENT_MAYBE_START;
|
||||
}
|
||||
else if (!isspace(c)) {
|
||||
pref_ReportParseProblem(*ps, "need space, comment or quote", lineNum, true);
|
||||
NS_WARNING("malformed pref file");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
/* parse until we find a comma separating name and value */
|
||||
case PREF_PARSE_UNTIL_COMMA:
|
||||
if (c == ',') {
|
||||
ps->vb = ps->lbcur;
|
||||
state = PREF_PARSE_UNTIL_VALUE;
|
||||
}
|
||||
else if (c == '/') { /* allow embedded comment */
|
||||
ps->nextstate = state; /* return here when done with comment */
|
||||
state = PREF_PARSE_COMMENT_MAYBE_START;
|
||||
}
|
||||
else if (!isspace(c)) {
|
||||
pref_ReportParseProblem(*ps, "need space, comment or comma", lineNum, true);
|
||||
NS_WARNING("malformed pref file");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
/* value parsing */
|
||||
case PREF_PARSE_UNTIL_VALUE:
|
||||
/* the pref value type is unknown. so, we scan for the first
|
||||
* character of the value, and determine the type from that. */
|
||||
if (c == '\"' || c == '\'') {
|
||||
ps->vtype = PrefType::String;
|
||||
ps->quotechar = c;
|
||||
ps->nextstate = PREF_PARSE_UNTIL_CLOSE_PAREN;
|
||||
state = PREF_PARSE_QUOTED_STRING;
|
||||
}
|
||||
else if (c == 't' || c == 'f') {
|
||||
ps->vb = (char *) (c == 't' ? kTrue : kFalse);
|
||||
ps->vtype = PrefType::Bool;
|
||||
ps->smatch = ps->vb;
|
||||
ps->sindex = 1;
|
||||
ps->nextstate = PREF_PARSE_UNTIL_CLOSE_PAREN;
|
||||
state = PREF_PARSE_MATCH_STRING;
|
||||
}
|
||||
else if (isdigit(c) || (c == '-') || (c == '+')) {
|
||||
ps->vtype = PrefType::Int;
|
||||
/* write c to line buffer... */
|
||||
if (ps->lbcur == ps->lbend && !pref_GrowBuf(ps))
|
||||
return false; /* out of memory */
|
||||
*ps->lbcur++ = c;
|
||||
state = PREF_PARSE_INT_VALUE;
|
||||
}
|
||||
else if (c == '/') { /* allow embedded comment */
|
||||
ps->nextstate = state; /* return here when done with comment */
|
||||
state = PREF_PARSE_COMMENT_MAYBE_START;
|
||||
}
|
||||
else if (!isspace(c)) {
|
||||
pref_ReportParseProblem(*ps, "need value, comment or space", lineNum, true);
|
||||
NS_WARNING("malformed pref file");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case PREF_PARSE_INT_VALUE:
|
||||
/* grow line buffer if necessary... */
|
||||
if (ps->lbcur == ps->lbend && !pref_GrowBuf(ps))
|
||||
return false; /* out of memory */
|
||||
if (isdigit(c))
|
||||
*ps->lbcur++ = c;
|
||||
else {
|
||||
*ps->lbcur++ = '\0'; /* stomp null terminator; we are done. */
|
||||
if (c == ')')
|
||||
state = PREF_PARSE_UNTIL_SEMICOLON;
|
||||
else if (c == '/') { /* allow embedded comment */
|
||||
ps->nextstate = PREF_PARSE_UNTIL_CLOSE_PAREN;
|
||||
state = PREF_PARSE_COMMENT_MAYBE_START;
|
||||
}
|
||||
else if (isspace(c))
|
||||
state = PREF_PARSE_UNTIL_CLOSE_PAREN;
|
||||
else {
|
||||
pref_ReportParseProblem(*ps, "while parsing integer", lineNum, true);
|
||||
NS_WARNING("malformed pref file");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
/* comment parsing */
|
||||
case PREF_PARSE_COMMENT_MAYBE_START:
|
||||
switch (c) {
|
||||
case '*': /* comment block */
|
||||
state = PREF_PARSE_COMMENT_BLOCK;
|
||||
break;
|
||||
case '/': /* comment line */
|
||||
state = PREF_PARSE_UNTIL_EOL;
|
||||
break;
|
||||
default:
|
||||
/* pref file is malformed */
|
||||
pref_ReportParseProblem(*ps, "while parsing comment", lineNum, true);
|
||||
NS_WARNING("malformed pref file");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case PREF_PARSE_COMMENT_BLOCK:
|
||||
if (c == '*')
|
||||
state = PREF_PARSE_COMMENT_BLOCK_MAYBE_END;
|
||||
break;
|
||||
case PREF_PARSE_COMMENT_BLOCK_MAYBE_END:
|
||||
switch (c) {
|
||||
case '/':
|
||||
state = ps->nextstate;
|
||||
ps->nextstate = PREF_PARSE_INIT;
|
||||
break;
|
||||
case '*': /* stay in this state */
|
||||
break;
|
||||
default:
|
||||
state = PREF_PARSE_COMMENT_BLOCK;
|
||||
}
|
||||
break;
|
||||
|
||||
/* string escape sequence parsing */
|
||||
case PREF_PARSE_ESC_SEQUENCE:
|
||||
/* not necessary to resize buffer here since we should be writing
|
||||
* only one character and the resize check would have been done
|
||||
* for us in the previous state */
|
||||
switch (c) {
|
||||
case '\"':
|
||||
case '\'':
|
||||
case '\\':
|
||||
break;
|
||||
case 'r':
|
||||
c = '\r';
|
||||
break;
|
||||
case 'n':
|
||||
c = '\n';
|
||||
break;
|
||||
case 'x': /* hex escape -- always interpreted as Latin-1 */
|
||||
case 'u': /* UTF16 escape */
|
||||
ps->esctmp[0] = c;
|
||||
ps->esclen = 1;
|
||||
ps->utf16[0] = ps->utf16[1] = 0;
|
||||
ps->sindex = (c == 'x' ) ?
|
||||
HEX_ESC_NUM_DIGITS :
|
||||
UTF16_ESC_NUM_DIGITS;
|
||||
state = PREF_PARSE_HEX_ESCAPE;
|
||||
continue;
|
||||
default:
|
||||
pref_ReportParseProblem(*ps, "preserving unexpected JS escape sequence",
|
||||
lineNum, false);
|
||||
NS_WARNING("preserving unexpected JS escape sequence");
|
||||
/* Invalid escape sequence so we do have to write more than
|
||||
* one character. Grow line buffer if necessary... */
|
||||
if ((ps->lbcur+1) == ps->lbend && !pref_GrowBuf(ps))
|
||||
return false; /* out of memory */
|
||||
*ps->lbcur++ = '\\'; /* preserve the escape sequence */
|
||||
break;
|
||||
}
|
||||
*ps->lbcur++ = c;
|
||||
state = PREF_PARSE_QUOTED_STRING;
|
||||
break;
|
||||
|
||||
/* parsing a hex (\xHH) or utf16 escape (\uHHHH) */
|
||||
case PREF_PARSE_HEX_ESCAPE:
|
||||
if ( c >= '0' && c <= '9' )
|
||||
udigit = (c - '0');
|
||||
else if ( c >= 'A' && c <= 'F' )
|
||||
udigit = (c - 'A') + 10;
|
||||
else if ( c >= 'a' && c <= 'f' )
|
||||
udigit = (c - 'a') + 10;
|
||||
else {
|
||||
/* bad escape sequence found, write out broken escape as-is */
|
||||
pref_ReportParseProblem(*ps, "preserving invalid or incomplete hex escape",
|
||||
lineNum, false);
|
||||
NS_WARNING("preserving invalid or incomplete hex escape");
|
||||
*ps->lbcur++ = '\\'; /* original escape slash */
|
||||
if ((ps->lbcur + ps->esclen) >= ps->lbend && !pref_GrowBuf(ps))
|
||||
return false;
|
||||
for (int i = 0; i < ps->esclen; ++i)
|
||||
*ps->lbcur++ = ps->esctmp[i];
|
||||
|
||||
/* push the non-hex character back for re-parsing. */
|
||||
/* (++buf at the top of the loop keeps this safe) */
|
||||
--buf;
|
||||
state = PREF_PARSE_QUOTED_STRING;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* have a digit */
|
||||
ps->esctmp[ps->esclen++] = c; /* preserve it */
|
||||
ps->utf16[1] <<= BITS_PER_HEX_DIGIT;
|
||||
ps->utf16[1] |= udigit;
|
||||
ps->sindex--;
|
||||
if (ps->sindex == 0) {
|
||||
/* have the full escape. Convert to UTF8 */
|
||||
int utf16len = 0;
|
||||
if (ps->utf16[0]) {
|
||||
/* already have a high surrogate, this is a two char seq */
|
||||
utf16len = 2;
|
||||
}
|
||||
else if (0xD800 == (0xFC00 & ps->utf16[1])) {
|
||||
/* a high surrogate, can't convert until we have the low */
|
||||
ps->utf16[0] = ps->utf16[1];
|
||||
ps->utf16[1] = 0;
|
||||
state = PREF_PARSE_UTF16_LOW_SURROGATE;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
/* a single utf16 character */
|
||||
ps->utf16[0] = ps->utf16[1];
|
||||
utf16len = 1;
|
||||
}
|
||||
|
||||
/* actual conversion */
|
||||
/* make sure there's room, 6 bytes is max utf8 len (in */
|
||||
/* theory; 4 bytes covers the actual utf16 range) */
|
||||
if (ps->lbcur+6 >= ps->lbend && !pref_GrowBuf(ps))
|
||||
return false;
|
||||
|
||||
ConvertUTF16toUTF8 converter(ps->lbcur);
|
||||
converter.write(ps->utf16, utf16len);
|
||||
ps->lbcur += converter.Size();
|
||||
state = PREF_PARSE_QUOTED_STRING;
|
||||
}
|
||||
break;
|
||||
|
||||
/* looking for beginning of utf16 low surrogate */
|
||||
case PREF_PARSE_UTF16_LOW_SURROGATE:
|
||||
if (ps->sindex == 0 && c == '\\') {
|
||||
++ps->sindex;
|
||||
}
|
||||
else if (ps->sindex == 1 && c == 'u') {
|
||||
/* escape sequence is correct, now parse hex */
|
||||
ps->sindex = UTF16_ESC_NUM_DIGITS;
|
||||
ps->esctmp[0] = 'u';
|
||||
ps->esclen = 1;
|
||||
state = PREF_PARSE_HEX_ESCAPE;
|
||||
}
|
||||
else {
|
||||
/* didn't find expected low surrogate. Ignore high surrogate
|
||||
* (it would just get converted to nothing anyway) and start
|
||||
* over with this character */
|
||||
--buf;
|
||||
if (ps->sindex == 1)
|
||||
state = PREF_PARSE_ESC_SEQUENCE;
|
||||
else
|
||||
state = PREF_PARSE_QUOTED_STRING;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
||||
/* function open and close parsing */
|
||||
case PREF_PARSE_UNTIL_OPEN_PAREN:
|
||||
/* tolerate only whitespace and embedded comments */
|
||||
if (c == '(')
|
||||
state = PREF_PARSE_UNTIL_NAME;
|
||||
else if (c == '/') {
|
||||
ps->nextstate = state; /* return here when done with comment */
|
||||
state = PREF_PARSE_COMMENT_MAYBE_START;
|
||||
}
|
||||
else if (!isspace(c)) {
|
||||
pref_ReportParseProblem(*ps, "need space, comment or open parentheses",
|
||||
lineNum, true);
|
||||
NS_WARNING("malformed pref file");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case PREF_PARSE_UNTIL_CLOSE_PAREN:
|
||||
/* tolerate only whitespace and embedded comments */
|
||||
if (c == ')') {
|
||||
state = PREF_PARSE_UNTIL_SEMICOLON;
|
||||
} else if (c == '/') {
|
||||
ps->nextstate = state; /* return here when done with comment */
|
||||
state = PREF_PARSE_COMMENT_MAYBE_START;
|
||||
} else if (!isspace(c)) {
|
||||
pref_ReportParseProblem(*ps, "need space, comment or closing parentheses",
|
||||
lineNum, true);
|
||||
NS_WARNING("malformed pref file");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
/* function terminator ';' parsing */
|
||||
case PREF_PARSE_UNTIL_SEMICOLON:
|
||||
/* tolerate only whitespace and embedded comments */
|
||||
if (c == ';') {
|
||||
if (!pref_DoCallback(ps))
|
||||
return false;
|
||||
state = PREF_PARSE_INIT;
|
||||
}
|
||||
else if (c == '/') {
|
||||
ps->nextstate = state; /* return here when done with comment */
|
||||
state = PREF_PARSE_COMMENT_MAYBE_START;
|
||||
}
|
||||
else if (!isspace(c)) {
|
||||
pref_ReportParseProblem(*ps, "need space, comment or semicolon",
|
||||
lineNum, true);
|
||||
NS_WARNING("malformed pref file");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
/* eol parsing */
|
||||
case PREF_PARSE_UNTIL_EOL:
|
||||
/* need to handle mac, unix, or dos line endings.
|
||||
* PREF_PARSE_INIT will eat the next \n in case
|
||||
* we have \r\n. */
|
||||
if (c == '\r' || c == '\n' || c == 0x1A) {
|
||||
state = ps->nextstate;
|
||||
ps->nextstate = PREF_PARSE_INIT; /* reset next state */
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
ps->state = state;
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef TEST_PREFREAD
|
||||
|
||||
static void
|
||||
pref_reader(void *closure,
|
||||
const char *pref,
|
||||
PrefValue val,
|
||||
PrefType type,
|
||||
bool defPref)
|
||||
{
|
||||
printf("%spref(\"%s\", ", defPref ? "" : "user_", pref);
|
||||
switch (type) {
|
||||
case PREF_STRING:
|
||||
printf("\"%s\");\n", val.stringVal);
|
||||
break;
|
||||
case PREF_INT:
|
||||
printf("%i);\n", val.intVal);
|
||||
break;
|
||||
case PREF_BOOL:
|
||||
printf("%s);\n", val.boolVal == false ? "false" : "true");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
PrefParseState ps;
|
||||
char buf[4096]; /* i/o buffer */
|
||||
FILE *fp;
|
||||
int n;
|
||||
|
||||
if (argc == 1) {
|
||||
printf("usage: prefread file.js\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
fp = fopen(argv[1], "r");
|
||||
if (!fp) {
|
||||
printf("failed to open file\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
PREF_InitParseState(&ps, pref_reader, nullptr, nullptr);
|
||||
|
||||
while ((n = fread(buf, 1, sizeof(buf), fp)) > 0)
|
||||
PREF_ParseBuf(&ps, buf, n);
|
||||
|
||||
PREF_FinalizeParseState(&ps);
|
||||
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* TEST_PREFREAD */
|
||||
Loading…
Add table
Add a link
Reference in a new issue