ghostscript源码分析之 scan_token()函数 (词法分析器iscan.c)

本文深入探讨了Ghostscript源码中的scan_token()函数,该函数在词法分析过程中扮演关键角色。虽然函数实现较为复杂且难以理解,作者通过添加中文注释以增进理解,并表达了对该函数设计的认可。同时提到了另一个挑战性的interp函数,虽然同样繁琐,但其设计思路被认为优于纯粹的递归方法。
摘要由CSDN通过智能技术生成

scan_token()函数很重要,ghostscript写得比较琐碎难懂,里面有些有英文解释。

我只对我关注的部分加了些中文注释。当然不是所有的都理解了。但是功能还是清楚了的,像某些函数接口。

如果让我写的话,我一定比他写得更清晰。哈哈,当然他的scan_token基本的框架

设计还是很赞同的。同时另外一个很困难的interp函数也给我这种感觉,很琐碎。但思想比较好,比纯递归高明些。

 

 

/*
 * Read a token from a stream.  Return 0 if an ordinary token was read,
 * >0 for special situations (see iscan.h).
 * If the token required a terminating character (i.e., was a name or
 * number) and the next character was whitespace, read and discard
 * that character.  Note that the state is relevant for e_VMerror
 * as well as for scan_Refill.
 */
int
scan_token(i_ctx_t *i_ctx_p, ref * pref, scanner_state * pstate)
{
    stream *const s = pstate->s_file.value.pfile;
    ref *myref = pref;
    int retcode = 0;
    int c;
/*
#define s_declare_inline(s, cp, ep)/
	register const byte *cp;/
	const byte *ep

#define s_begin_inline(s, cp, ep)/
	cp = (s)->srptr, ep = (s)->srlimit

#define s_end_inline(s, cp, ep)/
	(s)->srptr = cp

#define sputback_inline(s, cp, ep)/
	--cp
*/
    s_declare_inline(s, sptr, endptr);
#define scan_begin_inline() s_begin_inline(s, sptr, endptr)
#define scan_getc() sgetc_inline(s, sptr, endptr)
#define scan_putback() sputback_inline(s, sptr, endptr)
#define scan_end_inline() s_end_inline(s, sptr, endptr)
    const byte *newptr;
    byte *daptr;

#define sreturn(code)/
  { retcode = gs_note_error(code); goto sret; }
#define if_not_spush1()/
  if ( osp < ostop ) osp++;/
  else if ( (retcode = ref_stack_push(&o_stack, 1)) >= 0 )/
    ;/
  else
#define spop1()/
  if ( osp >= osbot ) osp--;/
  else ref_stack_pop(&o_stack, 1)
    int max_name_ctype =
	(recognize_btokens()? ctype_name : ctype_btoken);
/*用于数字*/
#define scan_sign(sign, ptr)/
  switch ( *ptr ) {/
    case '-': sign = -1; ptr++; break;/
    case '+': sign = 1; ptr++; break;/
    default: sign = 0;/
  }
/*回滚nback字符*/
#define refill2_back(styp,nback)/
  BEGIN sptr -= nback; scan_type = styp; goto pause; END
#define ensure2_back(styp,nback)/
  if ( sptr >= endptr ) refill2_back(styp,nback)
#define ensure2(styp) ensure2_back(styp, 1)
#define refill2(styp) refill2_back(styp, 1)
    byte s1[2];
    const byte *const decoder = scan_char_decoder;
    int status;
    int sign;
    const bool check_only = (pstate->s_options & SCAN_CHECK_ONLY) != 0;
    const bool PDFScanRules = (i_ctx_p->scanner_options & SCAN_PDF_RULES) != 0;
    /*
     * The following is a hack so that ^D will be self-delimiting in PS files
     * (to compensate for bugs in some PostScript-generating applications)
     * but not in strings (to match CPSI on the CET) or PDF.
     */
    const int ctrld = (pstate->s_options & SCAN_FROM_STRING ||
                      PDFScanRules ? 0x04 : 0xffff);
    scanner_state sstate;

#define pstack sstate.s_pstack
#define pdepth sstate.s_pdepth
#define scan_type sstate.s_scan_type
#define da sstate.s_da
#define name_type sstate.s_ss.s_name.s_name_type
#define try_number sstate.s_ss.s_name.s_try_number

    sptr = endptr = NULL; /* Quiet compiler */
    if (pstate->s_pstack != 0) {
	if_not_spush1()
	    return retcode;
	myref = osp;
    }
    /* Check whether we are resuming after an interruption. */
    if (pstate->s_scan_type != scanning_none) {
	sstate = *pstate;
	if (!da.is_dynamic && da.base != da.buf) {
	    /* The da contains some self-referencing pointers. */
	    /* Fix them up now. */
	    uint next = da.next - da.base;
	    uint limit = da.limit - da.base;

	    da.base = da.buf;
	    da.next = da.buf + next;
	    da.limit = da.buf + limit;
	}
	daptr = da.next;
	switch (scan_type) {
	    case scanning_binary:
		retcode = (*sstate.s_ss.binary.cont)
		    (i_ctx_p, myref, &sstate);
		scan_begin_inline();
		if (retcode == scan_Refill)
		    goto pause;
		goto sret;
	    case scanning_comment:
		scan_begin_inline();
		goto cont_comment;
	    case scanning_name:
		goto cont_name;
	    case scanning_string:
		goto cont_string;
	    default:
		return_error(e_Fatal);
	}
    }
    /* Fetch any state variables that are relevant even if */
    /* scan_type == scanning_none. */
    pstack = pstate->s_pstack;
    pdepth = pstate->s_pdepth;
    ref_assign(&sstate.s_file, &pstate->s_file);
    sstate.s_options = pstate->s_options;
    SCAN_INIT_ERROR(&sstate);
    scan_begin_inline();
    /*
     * Loop invariants:
     *      If pstack != 0, myref = osp, and *osp is a valid slot.
     */
  top:c = scan_getc();
    if_debug1('S', (c >= 32 && c <= 126 ? "`%c'" : c >= 0 ? "`//%03o'" : "`%d'
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yshuise

权术横行

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值