(一)ghostscript源码分析之interp()函数的第二个参数

/* Main interpreter. */ 
/* If execution terminates normally, return e_InterpreterExit. */
 /* If an error occurs, leave the current object in *perror_object */
 /* and return a (negative) error code. */ 
static int interp(i_ctx_t **pi_ctx_p /* context for execution, updated if resched */, const ref * pref /* object to interpret */, ref * perror_object) { 
i_ctx_t *i_ctx_p = *pi_ctx_p; /* * Note that iref may actually be either a ref * or a ref_packed *. * Certain DEC compilers assume that a ref * is ref-aligned even if it * is cast to a short *, and generate code on this assumption, leading * to "unaligned access" errors. For this reason, we declare * iref_packed, and use a macro to cast it to the more aligned type * where necessary (which is almost everywhere it is used). This may * lead to compiler warnings about "cast increases alignment * requirements", but this is less harmful than expensive traps at run * time. */
register const ref_packed *iref_packed = (const ref_packed *)pref;

interp函数的第二个参数是const ref* pref。

它来至于上层函数的调用:

 

下面的临时变量ref ifile;就是传入参数。

 

/* Open and run the very first initialization file. */
static int gs_run_init_file(gs_main_instance * minst, int *pexit_code, ref * perror_object) { 
i_ctx_t *i_ctx_p = minst->i_ctx_p;
 ref ifile;
 ref first_token;
 int code; 
scanner_state state; 
gs_main_set_lib_paths(minst); 
code = gs_main_run_file_open(minst, gs_init_file, &ifile); 
if (code < 0) { 
*pexit_code = 255;
 return code; 
} /* Check to make sure the first token is an integer */
 /* (for the version number check.) */ 
scanner_init(&state, &ifile);
 code = scan_token(i_ctx_p, &first_token, &state);
 if (code != 0 || !r_has_type(&first_token, t_integer))
 { 
eprintf1("Initialization file %s does not begin with an integer./n", gs_init_file); *pexit_code = 255; return_error(e_Fatal); }
 *++osp = first_token; 
r_set_attrs(&ifile, a_executable);
 return gs_main_interpret(minst, &ifile, minst->user_errors, pexit_code, perror_object); 
}

 

这个参数在函数gs_main_run_file_open中被修改:

int gs_main_run_file_open(gs_main_instance * minst, const char *file_name, ref * pfref) { gs_main_set_lib_paths(minst); 
if (gs_main_lib_open(minst, file_name, pfref) < 0)
{ eprintf1("Can't find initialization file %s./n", file_name); 
return_error(e_Fatal); 
}
r_set_attrs(pfref, a_execute + a_executable); 
return 0; }

被修改的语句是:

r_set_attrs(pfref, a_execute+a_executable);

而这句代码的实现为:

#define r_set_attrs(rp,mask) ((rp)->tas.type_attrs |= (mask))

也就是这个对象的type_attrs被修改了。而这个对象属性在interp函数中涉及到“分派”,是很重要的属性。

在gs_run_init_file ()中第一次调用scan_token()获得first_token,再把这个token放进操作符栈中。

 *++osp = first_token;这句实现这个功能。

后面还有一句:r_set_attrs(&ifile, a_executable);从这句调试来看这句并没有改别type_attrs的值。

这个ifile被传给interp函数之后,通过:

 

switch (r_type_xe(iref_packed)) { .............................. ............................. 
case exec(t_file): { /* Executable file. Read the next token and interpret it. */ 
stream *s;
 scanner_state sstate;
 check_read_known_file(s, IREF, return_with_error_iref); 
rt: if (iosp >= ostop) /* check early */ 
return_with_stackoverflow_iref(); 
osp = iosp; /* scan_token uses ostack */ 
scanner_init_options(&sstate, IREF, i_ctx_p->scanner_options); 
again:
 code = scan_token(i_ctx_p, &token, &sstate); 
iosp = osp; /* ditto */ switch (code) { 
case 0: /* read a token */ /* It's worth checking for literals, which make up */ /* the majority of input tokens, before storing the */ /* state on the e-stack. Note that because of //, */ /* the token may have *any* type and attributes. */ /* Note also that executable arrays aren't executed */ /* at the top level -- they're treated as literals. */ if (!r_has_attr(&token, a_executable) || r_is_array(&token) ) { 
/* If scan_token used the o-stack, */ /* we know we can do a push now; if not, */ /* the pre-check is still valid. */ 
iosp++;
ref_assign_inline(iosp, &token); 
goto rt; } 
store_state(iesp); .................... ...................... }

调用词法分析函数:scan_token()。

整个解析函数有两处调用scan_token()函数。

 

另外r_type_xe宏的实现在以前发过的文章关于iref.h中有讨论。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

yshuise

权术横行

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

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

打赏作者

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

抵扣说明:

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

余额充值