用于PS完整性测试的Ghostscript:终止于EOF,除非堆栈为空,否则返回错误

时间:2017-03-18 07:33:09

标签: testing ghostscript

为了测试PostScript文件的完整性,我想以下列方式运行Ghostscript:

  • 错误时返回1(或其他错误代码)
  • 如果堆栈为空,则在EOF返回0(成功)
  • 否则返回1(或其他错误代码)

我可以在后台运行 func updateChartData() { let chart = PieChartView(frame: self.view.frame) // 2. generate chart data entries let track = ["Income", "Expense", "Wallet", "Bank"] let money = [650, 456.13, 78.67, 856.52] var entries = [PieChartDataEntry]() for (index, value) in money.enumerated() { let entry = PieChartDataEntry() entry.y = value entry.label = track[index] entries.append( entry) } // 3. chart setup let set = PieChartDataSet( values: entries, label: "Pie Chart") // this is custom extension method. Download the code for more details. var colors: [UIColor] = [] for _ in 0..<money.count { let red = Double(arc4random_uniform(256)) let green = Double(arc4random_uniform(256)) let blue = Double(arc4random_uniform(256)) let color = UIColor(red: CGFloat(red/255), green: CGFloat(green/255), blue: CGFloat(blue/255), alpha: 1) colors.append(color) } set.colors = colors let data = PieChartData(dataSet: set) chart.data = data chart.noDataText = "No data available" // user interaction chart.isUserInteractionEnabled = true let d = Description() d.text = "iOSCharts.io" chart.chartDescription = d chart.centerText = "Pie Chart" chart.holeRadiusPercent = 0.2 chart.transparentCircleColor = UIColor.clear self.view.addSubview(chart) } ,如果gs与堆栈中剩余的项目挂起,则使用超时强制终止。有更简单的解决方案吗?

2 个答案:

答案 0 :(得分:1)

如果您将文件作为输入发送,Ghostscript将不会挂起(除非您编写的程序进入无限循环或无法达到暂停状态)。在任何堆栈上放置项目都不会导致它挂起。

另一方面,如果PostScript程序在操作数堆栈(或字典堆栈上的字典,剪辑堆栈上的剪辑或图形状态堆栈上的gstates)上留下操作数,它将不会出现错误。这是因为这不是错误,并且由于PostScript解释器通常在作业服务器循环中运行,因此它也不是问题。终止作业将控制返回到作业服务器循环,该循环对整个作业进行保存和恢复,从而清除遗留的任何内容。

我建议如果你真的想要这样做,你需要采用相同的方法,你需要编写一个PostScript程序来执行你想要'测试'的PostScript程序,然后检查操作数堆栈(和其他如果需要堆叠)以查看是否有任何遗留物。请注意,您将需要在已停止的上下文中执行测试程序,因为程序过程中的错误显然可能会留下任何东西。

如果我没记错的话,Ghostscript会在干净的退出时返回0,并且对于错误返回小于0的值。您需要在测试框架中使用signalerror,以便在项目结束时留下项目时引发错误。

[编辑]

在命令行上由-s或-d提供给Ghostscript的任何内容都在systemdict中定义,所以如果我们-sInputFileName=/test.pdf,我们会在systemdict中找到一个键/InputFileName,其值为字符串内容为(/test.pdf)。我们可以使用它将文件名传递给我们的程序。

stopped运算符将可执行数组作为参数,并返回true或false,具体取决于执行数组时是否发生错误(第3版PLRM,第697页)。

因此我们需要运行我们已经给出的文件名中包含的程序,并在“已停止”的上下文中执行。像这样:

{InputFileName run} stopped
{
  (Error occurred\n) print flush
  %% Potentially check $error for more information.
}{
  (program terminated normally\n) print flush
  %% Here you could check the various stacks
} ifelse

答案 1 :(得分:0)

根据KenS的答案,以下90%的答案是99%令人满意:

计划checkIntegrity.ps

{Script run} stopped
{
   (\n===> Integrity test failed: ) print Script print ( has error\n\n) print
   handleerror
   (ignore this error which only serves to force a return value of 1) /syntaxerror signalerror
}{
   % script passed, now check the stack
   count dup 0 eq {
      pop (\n===> Integrity test passed: ) print Script print ( terminated normally\n\n) print
   } {
      (\n===> Integrity test failed: ) print Script print ( left ) print
      3 string cvs print ( item(s) on stack\n\n) print
      Script /syntaxerror signalerror
   } ifelse
} ifelse
quit

执行

gs -q -sScript=CodeToBeChecked.ps checkIntegrity.ps ; echo $?

对于最后1%的满意度,我需要替换

(blabla) /syntaxerror signalerror

它强制退出并返回代码1,但是非常冗长,并且会分散handleerror报告的已检查脚本中的实际错误。因此,欢迎exit(1)更清洁的方式。