📄 psobjs.c
字号:
break; if ( !IS_PS_XDIGIT( *cur ) ) break; } if ( cur < limit && *cur != '>' ) { FT_ERROR(( "skip_string: missing closing delimiter `>'\n" )); err = PSaux_Err_Invalid_File_Format; } else cur++; *acur = cur; return err; } /* first character must be the opening brace that */ /* starts the procedure */ /* NB: [ and ] need not match: */ /* `/foo {[} def' is a valid PostScript fragment, */ /* even within a Type1 font */ static FT_Error skip_procedure( FT_Byte* *acur, FT_Byte* limit ) { FT_Byte* cur; FT_Int embed = 0; FT_Error error = PSaux_Err_Ok; FT_ASSERT( **acur == '{' ); for ( cur = *acur; cur < limit && error == PSaux_Err_Ok; ++cur ) { switch ( *cur ) { case '{': ++embed; break; case '}': --embed; if ( embed == 0 ) { ++cur; goto end; } break; case '(': error = skip_literal_string( &cur, limit ); break; case '<': error = skip_string( &cur, limit ); break; case '%': skip_comment( &cur, limit ); break; } } end: if ( embed != 0 ) error = PSaux_Err_Invalid_File_Format; *acur = cur; return error; } /***********************************************************************/ /* */ /* All exported parsing routines handle leading whitespace and stop at */ /* the first character which isn't part of the just handled token. */ /* */ /***********************************************************************/ FT_LOCAL_DEF( void ) ps_parser_skip_PS_token( PS_Parser parser ) { /* Note: PostScript allows any non-delimiting, non-whitespace */ /* character in a name (PS Ref Manual, 3rd ed, p31). */ /* PostScript delimiters are (, ), <, >, [, ], {, }, /, and %. */ FT_Byte* cur = parser->cursor; FT_Byte* limit = parser->limit; FT_Error error = PSaux_Err_Ok; skip_spaces( &cur, limit ); /* this also skips comments */ if ( cur >= limit ) goto Exit; /* self-delimiting, single-character tokens */ if ( *cur == '[' || *cur == ']' ) { cur++; goto Exit; } /* skip balanced expressions (procedures and strings) */ if ( *cur == '{' ) /* {...} */ { error = skip_procedure( &cur, limit ); goto Exit; } if ( *cur == '(' ) /* (...) */ { error = skip_literal_string( &cur, limit ); goto Exit; } if ( *cur == '<' ) /* <...> */ { if ( cur + 1 < limit && *(cur + 1) == '<' ) /* << */ { cur++; cur++; } else error = skip_string( &cur, limit ); goto Exit; } if ( *cur == '>' ) { cur++; if ( cur >= limit || *cur != '>' ) /* >> */ { FT_ERROR(( "ps_parser_skip_PS_token: " "unexpected closing delimiter `>'\n" )); error = PSaux_Err_Invalid_File_Format; goto Exit; } cur++; goto Exit; } if ( *cur == '/' ) cur++; /* anything else */ while ( cur < limit ) { /* *cur might be invalid (e.g., ')' or '}'), but this */ /* is handled by the test `cur == parser->cursor' below */ if ( IS_PS_DELIM( *cur ) ) break; cur++; } Exit: if ( cur == parser->cursor ) { FT_ERROR(( "ps_parser_skip_PS_token: " "current token is `%c', which is self-delimiting " "but invalid at this point\n", *cur )); error = PSaux_Err_Invalid_File_Format; } FT_ASSERT( parser->error == PSaux_Err_Ok ); parser->error = error; parser->cursor = cur; } FT_LOCAL_DEF( void ) ps_parser_skip_spaces( PS_Parser parser ) { skip_spaces( &parser->cursor, parser->limit ); } /* `token' here means either something between balanced delimiters */ /* or the next token; the delimiters are not removed. */ FT_LOCAL_DEF( void ) ps_parser_to_token( PS_Parser parser, T1_Token token ) { FT_Byte* cur; FT_Byte* limit; FT_Int embed; token->type = T1_TOKEN_TYPE_NONE; token->start = 0; token->limit = 0; /* first of all, skip leading whitespace */ ps_parser_skip_spaces( parser ); cur = parser->cursor; limit = parser->limit; if ( cur >= limit ) return; switch ( *cur ) { /************* check for literal string *****************/ case '(': token->type = T1_TOKEN_TYPE_STRING; token->start = cur; if ( skip_literal_string( &cur, limit ) == PSaux_Err_Ok ) token->limit = cur; break; /************* check for programs/array *****************/ case '{': token->type = T1_TOKEN_TYPE_ARRAY; token->start = cur; if ( skip_procedure( &cur, limit ) == PSaux_Err_Ok ) token->limit = cur; break; /************* check for table/array ********************/ /* XXX: in theory we should also look for "<<" */ /* since this is semantically equivalent to "["; */ /* in practice it doesn't matter (?) */ case '[': token->type = T1_TOKEN_TYPE_ARRAY; embed = 1; token->start = cur++; /* we need this to catch `[ ]' */ parser->cursor = cur; ps_parser_skip_spaces( parser ); cur = parser->cursor; while ( cur < limit && !parser->error ) { /* XXX: this is wrong because it does not */ /* skip comments, procedures, and strings */ if ( *cur == '[' ) embed++; else if ( *cur == ']' ) { embed--; if ( embed <= 0 ) { token->limit = ++cur; break; } } parser->cursor = cur; ps_parser_skip_PS_token( parser ); /* we need this to catch `[XXX ]' */ ps_parser_skip_spaces ( parser ); cur = parser->cursor; } break; /* ************ otherwise, it is any token **************/ default: token->start = cur; token->type = ( *cur == '/' ? T1_TOKEN_TYPE_KEY : T1_TOKEN_TYPE_ANY ); ps_parser_skip_PS_token( parser ); cur = parser->cursor; if ( !parser->error ) token->limit = cur; } if ( !token->limit ) { token->start = 0; token->type = T1_TOKEN_TYPE_NONE; } parser->cursor = cur; } /* NB: `tokens' can be NULL if we only want to count */ /* the number of array elements */ FT_LOCAL_DEF( void ) ps_parser_to_token_array( PS_Parser parser, T1_Token tokens, FT_UInt max_tokens, FT_Int* pnum_tokens ) { T1_TokenRec master; *pnum_tokens = -1; /* this also handles leading whitespace */ ps_parser_to_token( parser, &master ); if ( master.type == T1_TOKEN_TYPE_ARRAY ) { FT_Byte* old_cursor = parser->cursor; FT_Byte* old_limit = parser->limit; T1_Token cur = tokens; T1_Token limit = cur + max_tokens; /* don't include outermost delimiters */ parser->cursor = master.start + 1; parser->limit = master.limit - 1; while ( parser->cursor < parser->limit ) { T1_TokenRec token; ps_parser_to_token( parser, &token ); if ( !token.type ) break; if ( tokens != NULL && cur < limit ) *cur = token; cur++; } *pnum_tokens = (FT_Int)( cur - tokens ); parser->cursor = old_cursor; parser->limit = old_limit; } } /* first character must be a delimiter or a part of a number */ /* NB: `coords' can be NULL if we just want to skip the */ /* array; in this case we ignore `max_coords' */ static FT_Int ps_tocoordarray( FT_Byte* *acur, FT_Byte* limit, FT_Int max_coords, FT_Short* coords ) { FT_Byte* cur = *acur; FT_Int count = 0; FT_Byte c, ender; if ( cur >= limit ) goto Exit; /* check for the beginning of an array; otherwise, only one number */ /* will be read */ c = *cur; ender = 0; if ( c == '[' ) ender = ']'; if ( c == '{' ) ender = '}'; if ( ender ) cur++; /* now, read the coordinates */ while ( cur < limit ) { FT_Short dummy; /* skip whitespace in front of data */ skip_spaces( &cur, limit ); if ( cur >= limit ) goto Exit; if ( coords != NULL && count >= max_coords ) break; if ( *cur == ender ) { cur++; break; } /* call PS_Conv_ToFixed() even if coords == NULL */ /* to properly parse number at `cur' */ *( coords != NULL ? &coords[count] : &dummy ) = (FT_Short)( PS_Conv_ToFixed( &cur, limit, 0 ) >> 16 ); count++; if ( !ender ) break; } Exit: *acur = cur; return count; } /* first character must be a delimiter or a part of a number */ /* NB: `values' can be NULL if we just want to skip the */ /* array in this case we ignore `max_values' */ static FT_Int ps_tofixedarray( FT_Byte* *acur, FT_Byte* limit, FT_Int max_values,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -