w32tex
About: TeX Live provides a comprehensive TeX system including all the major TeX-related programs, macro packages, and fonts that are free software. Windows sources.
  Fossies Dox: w32tex-src.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

dvi.c
Go to the documentation of this file.
1 /* dvi.c */
2 
3 /************************************************************************
4 
5  Part of the dvipng distribution
6 
7  This program is free software: you can redistribute it and/or modify
8  it under the terms of the GNU Lesser General Public License as
9  published by the Free Software Foundation, either version 3 of the
10  License, or (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful, but
13  WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  Lesser General Public License for more details.
16 
17  You should have received a copy of the GNU Lesser General Public
18  License along with this program. If not, see
19  <http://www.gnu.org/licenses/>.
20 
21  Copyright (C) 2002-2015, 2019 Jan-Åke Larsson
22 
23 ************************************************************************/
24 
25 #include "dvipng.h"
26 #ifdef MIKTEX
27 # include <gnu-miktex.h>
28 # define USLEEP Sleep
29 #else /* MIKTEX */
30 # ifdef HAVE_LIBGEN_H
31 # include <libgen.h>
32 # else
33 # define basename xbasename
34 # endif
35 # ifdef WIN32
36 # define USLEEP Sleep
37 # include <stdlib.h>
38 # else
39 # include <unistd.h>
40 # define USLEEP usleep
41 # endif /* WIN32 */
42 #endif /* MIKTEX */
43 #include <sys/stat.h>
44 #include <fcntl.h>
45 
46 bool followmode=0;
47 
48 bool DVIFollowToggle(void)
49 {
50  return followmode = ! followmode;
51 }
52 
53 static unsigned char fgetc_follow(FILE* fp)
54 {
55  int got=fgetc(fp),nsleep=1;
56 
57  while(followmode && got==EOF) {
58  USLEEP(nsleep/1310); /* After a few trials, poll every 65536/1310=50 usec */
59  clearerr(fp);
60  got=fgetc(fp);
61  if (nsleep<50000)
62  nsleep*=2;
63  }
64  if (got==EOF)
65  Fatal("DVI file ends prematurely");
66  return (unsigned char)got;
67 }
68 
69 static void DVIInit(struct dvi_data* dvi)
70 {
71  int k;
72  unsigned char* pre;
73  struct stat stat;
74 
75  fseek(dvi->filep,0,SEEK_SET);
77  if (*pre != PRE) {
78  Fatal("PRE does not occur first - are you sure this is a DVI file?");
79  }
80  k = UNumRead(pre+1,1);
81  DEBUG_PRINT(DEBUG_DVI,("DVI START:\tPRE %d",k));
82  if (k != DVIFORMAT) {
83  Fatal("DVI format = %d, can only process DVI format %d files",
84  k, DVIFORMAT);
85  }
86  dvi->num = UNumRead(pre+2, 4);
87  dvi->den = UNumRead(pre+6, 4);
88  DEBUG_PRINT(DEBUG_DVI,(" %d/%d",dvi->num,dvi->den));
89  dvi->mag = UNumRead(pre+10, 4); /*FIXME, see font.c*/
90  DEBUG_PRINT(DEBUG_DVI,(" %d",dvi->mag));
91  if ( usermag > 0 && usermag != dvi->mag ) {
92  Warning("DVI magnification of %d over-ridden by user (%ld)",
93  (long)dvi->mag, usermag );
94  dvi->mag = usermag;
95  }
96  dvi->conv = (1.0/(((double)dvi->num / (double)dvi->den) *
97  ((double)dvi->mag / 1000.0) *
98  ((double)dpi*shrinkfactor/254000.0)))+0.5;
99  DEBUG_PRINT(DEBUG_DVI,(" (%d)",dvi->conv));
100  k = UNumRead(pre+14,1);
101  DEBUG_PRINT(DEBUG_DVI,(" '%.*s'",k,pre+15));
102  Message(BE_VERBOSE,"'%.*s' -> %s\n",k,pre+15,dvi->outname);
103  fstat(fileno(dvi->filep), &stat);
104  dvi->mtime = stat.st_mtime;
105  dvi->pagelistp=NULL;
106  dvi->flags = 0;
107 }
108 
109 struct dvi_data* DVIOpen(char* dviname,char* outname)
110 {
111  char* tmpstring;
112  struct dvi_data* dvi;
113 
114  if ((dvi = calloc(1,sizeof(struct dvi_data)))==NULL)
115  Fatal("cannot allocate memory for DVI struct");
116  dvi->type = DVI_TYPE;
117  dvi->fontnump=NULL;
118  if ((dvi->name = malloc(strlen(dviname)+5))==NULL)
119  Fatal("cannot allocate space for DVI filename");
120  strcpy(dvi->name, dviname);
121  tmpstring = strrchr(dvi->name, '.');
122  if (tmpstring == NULL || strcmp(tmpstring,".dvi") != 0)
123  strcat(dvi->name, ".dvi");
124  if (outname==NULL) {
125  if ((dvi->outname = malloc(strlen(basename(dviname))+7))==NULL) {
126  free(dvi->name);
127  free(dvi);
128  Fatal("cannot allocate space for output filename");
129  }
130  strcpy(dvi->outname,basename(dviname));
131  tmpstring = strrchr(dvi->outname, '.');
132  if (tmpstring != NULL && strcmp(tmpstring,".dvi") == 0)
133  *tmpstring = '\0';
134  strcat(dvi->outname, "%d.png");
135  } else {
136  if ((dvi->outname = malloc(strlen(outname)+1))==NULL) {
137  free(dvi->name);
138  free(dvi);
139  Fatal("cannot allocate space for output filename");
140  }
142  }
143  if ((dvi->filep = fopen(dvi->name,"rb")) == NULL) {
144  /* do not insist on .dvi */
145  tmpstring = strrchr(dvi->name, '.');
146  *tmpstring='\0';
147  dvi->filep = fopen(dvi->name,"rb");
148  }
149  while((dvi->filep == NULL) && followmode) {
150  USLEEP(50);
151  *tmpstring='.';
152  if ((dvi->filep = fopen(dvi->name,"rb")) == NULL) {
153  /* do not insist on .dvi */
154  *tmpstring='\0';
155  dvi->filep = fopen(dvi->name,"rb");
156  }
157  }
158  if (dvi->filep == NULL) {
159  free(dvi->name);
160  free(dvi->outname);
161  free(dvi);
162  perror(dviname);
163  exit (EXIT_FAILURE);
164  }
165  DEBUG_PRINT(DEBUG_DVI,("OPEN FILE\t%s", dvi->name));
166  DVIInit(dvi);
167  return(dvi);
168 }
169 
170 unsigned char* DVIGetCommand(struct dvi_data* dvi)
171  /* This function reads in and stores the next dvi command. */
172  /* Mmap is not appropriate here, we may want to read from
173  half-written files. */
174 {
175  static unsigned char* command=NULL;
176  static uint32_t commlen=0;
177  unsigned char *current = command;
178  int length;
179  uint32_t strlength=0;
180 
181  if (commlen==0) {
182  commlen=STRSIZE;
183  if ((current=command=malloc(commlen))==NULL)
184  Fatal("cannot allocate memory for DVI command");
185  }
186  DEBUG_PRINT(DEBUG_DVI,("\n@%ld ", ftell(dvi->filep)));
187  *(current++) = fgetc_follow(dvi->filep);
189  if (length < 0)
190  Fatal("undefined DVI op-code %d",*command);
191  while(current < command+length)
192  *(current++) = fgetc_follow(dvi->filep);
193  switch (*command) {
194  case XXX4:
195  strlength = *(current - 4);
196  case XXX3:
197  strlength = strlength * 256 + *(current - 3);
198  case XXX2:
199  strlength = strlength * 256 + *(current - 2);
200  case XXX1:
201  strlength = strlength * 256 + *(current - 1);
202  break;
203  case FNT_DEF1: case FNT_DEF2: case FNT_DEF3: case FNT_DEF4:
204  strlength = *(current - 1) + *(current - 2);
205  break;
206  case PRE:
207  strlength = *(current - 1);
208  break;
209  }
210  if (strlength > 0) { /* Read string */
211  if (strlength > UINT32_MAX - (uint32_t)length - 1)
212  Fatal("integer overflow in DVI command length");
213  if (strlength+1 + (uint32_t)length > commlen) {
214  /* string + command length exceeds that of buffer */
215  commlen=strlength+1 + (uint32_t)length;
216  if ((command=realloc(command,commlen))==NULL)
217  Fatal("cannot allocate memory for DVI command");
218  current = command + length;
219  }
220  while(current < command+length+strlength)
221  *(current++) = fgetc_follow(dvi->filep);
222  *current='\0';
223  }
224  return(command);
225 }
226 
228  /* This function checks if the next dvi command is a raw PS
229  special */
230  /* Mmap is not appropriate here, we may want to read from
231  half-written files. */
232 {
233  long fpos;
234  uint32_t strlength=0;
235  bool israwps=false;
236 
237  DEBUG_PRINT(DEBUG_DVI,("\n CHECKING NEXT DVI COMMAND "));
238  fpos=ftell(dvi->filep);
239  switch (fgetc_follow(dvi->filep)) {
240  case XXX4:
241  strlength = fgetc_follow(dvi->filep);
242  case XXX3:
243  strlength = strlength * 256 + fgetc_follow(dvi->filep);
244  case XXX2:
245  strlength = strlength * 256 + fgetc_follow(dvi->filep);
246  case XXX1:
247  strlength = strlength * 256 + fgetc_follow(dvi->filep);
248  }
249  if (strlength > 0) {
250  switch(fgetc_follow(dvi->filep)) {
251  case 'p':
252  if (strlength > 2
253  && fgetc_follow(dvi->filep)=='s'
254  && fgetc_follow(dvi->filep)==':')
255  israwps=true;
256  break;
257  case '"':
258  israwps=true;
259  }
260  }
261  fseek(dvi->filep,fpos,SEEK_SET);
262  return(israwps);
263 }
264 
266 {
267  /* generally 2^32+5 bytes max, but in practice 32 bit numbers suffice */
268  uint32_t length=0;
269 
271  switch (*command) {
272  case XXX1: case XXX2: case XXX3: case XXX4:
273  length += UNumRead(command + 1,length - 1);
274  break;
275  case FNT_DEF1: case FNT_DEF2: case FNT_DEF3: case FNT_DEF4:
276  length += *(command + length - 1) + *(command + length - 2);
277  break;
278  case PRE:
279  length += *(command + length - 1);
280  break;
281  }
282  return(length);
283 }
284 
285 static void SkipPage(struct dvi_data* dvi)
286 {
287  /* Skip present page */
288  unsigned char* command;
289 
291  while (*command != EOP) {
292  switch (*command) {
293  case FNT_DEF1: case FNT_DEF2: case FNT_DEF3: case FNT_DEF4:
294  DEBUG_PRINT(DEBUG_DVI,("NOSKIP CMD:\t%s", dvi_commands[*command]));
296  break;
297  case XXX1: case XXX2: case XXX3: case XXX4:
298  DEBUG_PRINT(DEBUG_DVI,("NOSKIP CMD:\t%s %d", dvi_commands[*command],
303  0,0);
304  break;
305  case BOP: case PRE: case POST: case POST_POST:
306  Fatal("%s occurs within page", dvi_commands[*command]);
307  break;
308 #ifdef DEBUG
309  default:
310  DEBUG_PRINT(DEBUG_DVI,("SKIP CMD:\t%s", dvi_commands[*command]));
311 #endif
312  }
314  } /* while */
315  DEBUG_PRINT(DEBUG_DVI,("SKIP CMD:\t%s", dvi_commands[*command]));
316 }
317 
318 static struct page_list* InitPage(struct dvi_data* dvi)
319 {
320  /* Find page start, return pointer to page_list entry if found */
321  struct page_list* tpagelistp=NULL;
322  unsigned char* command;
323 
325  /* Skip until page start or postamble */
326  while((*command != BOP) && (*command != POST)) {
327  switch(*command) {
328  case FNT_DEF1: case FNT_DEF2: case FNT_DEF3: case FNT_DEF4:
329  DEBUG_PRINT(DEBUG_DVI,("NOPAGE CMD:\t%s", dvi_commands[*command]));
331  break;
332  case NOP:
333  DEBUG_PRINT(DEBUG_DVI,("NOPAGE CMD:\tNOP"));
334  break;
335  default:
336  Fatal("%s occurs outside page", dvi_commands[*command]);
337  }
339  }
340  if ((tpagelistp =
341  malloc(sizeof(struct page_list)
342  +(csp+1-2)*sizeof(struct dvi_color)))==NULL)
343  Fatal("cannot allocate memory for new page entry");
344  tpagelistp->next = NULL;
345  if ( *command == BOP ) { /* Init page */
346  int i;
347  DEBUG_PRINT(DEBUG_DVI,("PAGE START:\tBOP"));
348  StoreColorStack(tpagelistp);
349  tpagelistp->offset = ftell(dvi->filep)-45;
350  for (i = 0; i <= 9; i++) {
351  tpagelistp->count[i] = UNumRead(command + 1 + i*4, 4);
352  DEBUG_PRINT(DEBUG_DVI,(" %d",tpagelistp->count[i]));
353  }
354  if (dvi->pagelistp==NULL)
355  tpagelistp->count[10] = 1;
356  else
357  tpagelistp->count[10] = dvi->pagelistp->count[10]+1;
358  DEBUG_PRINT(DEBUG_DVI,(" (%d)", tpagelistp->count[10]));
359  } else {
360  DEBUG_PRINT(DEBUG_DVI,("DVI END:\tPOST"));
361  tpagelistp->offset = ftell(dvi->filep)-1;
362  tpagelistp->count[0] = PAGE_POST; /* POST */
363  tpagelistp->count[10] = PAGE_POST; /* POST */
364  }
365  return(tpagelistp);
366 }
367 
368 int SeekPage(struct dvi_data* dvi, struct page_list* page)
369 {
371  return(fseek(dvi->filep,
372  page->offset+((page->count[0]==PAGE_POST) ? 1L : 45L),
373  SEEK_SET));
374 }
375 
376 struct page_list* NextPage(struct dvi_data* dvi, struct page_list* page)
377 {
378  struct page_list* tpagelistp;
379 
380  /* if page points to POST there is no next page */
381  if (page!=NULL && page->count[0]==PAGE_POST)
382  return(NULL);
383 
384  /* If we have read past the last page in our current list or the
385  * list is empty, sneak a look at the next page
386  */
387  if (dvi->pagelistp==NULL
388  || dvi->pagelistp->offset+45L < ftell(dvi->filep)) {
389  tpagelistp=dvi->pagelistp;
391  dvi->pagelistp->next=tpagelistp;
392  }
393 
394  if (page!=dvi->pagelistp) {
395  /* also works if page==NULL, we'll get the first page then */
396  tpagelistp=dvi->pagelistp;
397  while(tpagelistp!=NULL && tpagelistp->next!=page)
398  tpagelistp=tpagelistp->next;
399  } else {
400  /* dvi->pagelistp points to the last page we've read so far,
401  * the last page that we know where it is, so to speak
402  * So look at the next
403  */
405  SkipPage(dvi);
406  tpagelistp=dvi->pagelistp;
408  dvi->pagelistp->next=tpagelistp;
409  tpagelistp=dvi->pagelistp;
410  }
411  return(tpagelistp);
412 }
413 
414 struct page_list* PrevPage(struct dvi_data* dvi, struct page_list* page)
415 {
416  return(page->next);
417 }
418 
419 
421  /* Find first page of certain number,
422  absolute number if abspage is set */
423 {
424  struct page_list* page=NextPage(dvi, NULL);
425 
427  while(page!=NULL && page->count[0]!=PAGE_POST)
429  if (pagenum==PAGE_LASTPAGE)
431  } else
432  if (pagenum!=PAGE_FIRSTPAGE)
433  while(page != NULL && pagenum != page->count[abspage ? 0 : 10])
435  return(page);
436 }
437 
438 
439 static void DelPageList(struct dvi_data* dvi)
440 {
441  struct page_list* temp;
442 
443  /* Delete the page list */
444 
445  temp=dvi->pagelistp;
446  while(temp!=NULL) {
448  free(temp);
449  temp=dvi->pagelistp;
450  }
451 }
452 
453 void DVIClose(struct dvi_data* dvi)
454 {
455  if (dvi!=NULL) {
456  fclose(dvi->filep);
457  DelPageList(dvi);
458  ClearPSHeaders();
459  free(dvi->outname);
460  free(dvi->name);
461  free(dvi);
462  }
463 }
464 
465 bool DVIReOpen(struct dvi_data* dvi)
466 {
467  struct stat stat;
468  fstat(fileno(dvi->filep), &stat);
469  if (dvi->mtime != stat.st_mtime) {
470  fclose(dvi->filep);
471  dvi->filep=NULL;
472  DelPageList(dvi);
473  ClearPSHeaders();
474  while(((dvi->filep = fopen(dvi->name,"rb")) == NULL) && followmode) {
475  USLEEP(50);
476  }
477  if (dvi->filep == NULL) {
478  perror(dvi->name);
480  }
481  Message(PARSE_STDIN,"Reopened file\n");
482  DEBUG_PRINT(DEBUG_DVI,("\nREOPEN FILE\t%s", dvi->name));
483  DVIInit(dvi);
484  return(true);
485  }
486  return(false);
487 }
void __cdecl perror(char const *_ErrMsg)
@ pre
Definition: ctie-k.c:71
#define free(a)
Definition: decNumber.cpp:310
#define strrchr
Definition: detex.c:67
void Warning(const char *sb1, const char *sb2)
Definition: detex.c:4677
#define EOP
Definition: dtl.h:133
#define BOP
Definition: dtl.h:132
#define DVIFORMAT
Definition: defs.h:136
int usermag
Definition: dvi2.c:51
void Fatal()
#define fopen
Definition: xxstdio.h:21
#define fseek
Definition: xxstdio.h:30
#define fgetc
Definition: xxstdio.h:26
#define ftell
Definition: xxstdio.h:31
#define DEBUG_PRINT(str)
Definition: dvi2xx.h:670
int strcmp()
Definition: coll.cpp:143
char * strcpy()
char * temp
Definition: dvidvi.c:137
void StoreColorStack(struct page_list *tpagep)
Definition: color.c:402
void ReadColorStack(struct page_list *tpagep)
Definition: color.c:418
#define PARSE_STDIN
Definition: dvipng.h:386
void Message(int, const char *fmt,...)
Definition: misc.c:754
void SetSpecial(char *, char *, int32_t, int32_t)
int csp
#define DVI_TYPE
Definition: dvipng.h:126
#define BE_VERBOSE
Definition: dvipng.h:385
struct dvi_data * dvi
void ClearPSHeaders(void)
Definition: special.c:97
#define PAGE_LASTPAGE
Definition: dvipng.h:146
uint32_t UNumRead(unsigned char *, register int)
Definition: misc.c:690
#define PAGE_FIRSTPAGE
Definition: dvipng.h:148
#define PAGE_POST
Definition: dvipng.h:145
void FontDef(unsigned char *, void *)
Definition: font.c:67
#define DEBUG_DVI
Definition: dvipng.h:415
int32_t shrinkfactor
static void
Definition: fpif.c:118
#define STRSIZE
#define PRE
Definition: hbf2gf.c:42
#define XXX3
Definition: hbf2gf.c:55
#define XXX2
Definition: hbf2gf.c:54
#define POST
Definition: hbf2gf.c:60
#define XXX1
Definition: hbf2gf.c:53
#define XXX4
Definition: hbf2gf.c:56
#define EXIT_FAILURE
Definition: cdjpeg.h:169
#define SEEK_SET
Definition: jmemansi.c:26
#define NULL
Definition: ftobjs.h:61
small capitals from c petite p scientific i
Definition: afcover.h:80
void exit()
#define EOF
Definition: afmparse.c:59
unsigned int uint32_t
Definition: stdint.h:80
signed int int32_t
Definition: stdint.h:77
#define UINT32_MAX
Definition: stdint.h:142
static char * outname
Definition: pngtest.c:1818
voidp calloc()
#define POST_POST
Definition: commands.h:259
#define FNT_DEF1
Definition: commands.h:253
#define FNT_DEF3
Definition: commands.h:255
#define FNT_DEF2
Definition: commands.h:254
#define FNT_DEF4
Definition: commands.h:256
int command
Definition: dviconv.c:23
EXTERN const char * dvi_commands[256]
Definition: commands.h:195
EXTERN const int8_t dvi_commandlength[256]
Definition: commands.h:135
boolean DVIIsNextPSSpecial(struct dvi_data *dvi)
Definition: dvi.c:227
static struct page_list * InitPage(struct dvi_data *dvi)
Definition: dvi.c:318
#define USLEEP
Definition: dvi.c:40
void DVIClose(struct dvi_data *dvi)
Definition: dvi.c:453
boolean DVIFollowToggle(void)
Definition: dvi.c:48
boolean followmode
Definition: dvi.c:46
struct page_list * PrevPage(struct dvi_data *dvi, struct page_list *page)
Definition: dvi.c:414
#define basename
Definition: dvi.c:33
static void SkipPage(struct dvi_data *dvi)
Definition: dvi.c:285
struct dvi_data * DVIOpen(char *dviname, char *outname)
Definition: dvi.c:109
static unsigned char fgetc_follow(FILE *fp)
Definition: dvi.c:53
static void DVIInit(struct dvi_data *dvi)
Definition: dvi.c:69
static void DelPageList(struct dvi_data *dvi)
Definition: dvi.c:439
struct page_list * FindPage(struct dvi_data *dvi, int32_t pagenum, boolean abspage)
Definition: dvi.c:420
unsigned char * DVIGetCommand(struct dvi_data *dvi)
Definition: dvi.c:170
struct page_list * NextPage(struct dvi_data *dvi, struct page_list *page)
Definition: dvi.c:376
int SeekPage(struct dvi_data *dvi, struct page_list *page)
Definition: dvi.c:368
uint32_t CommandLength(unsigned char *command)
Definition: dvi.c:265
boolean DVIReOpen(struct dvi_data *dvi)
Definition: dvi.c:465
#define fclose
Definition: debug.h:100
#define fileno
Definition: win32lib.h:72
#define fstat
Definition: win32lib.h:74
#define length(c)
Definition: ctangleboot.c:65
#define malloc
Definition: alloca.c:91
#define NOP
Definition: tif_getimage.c:684
#define realloc
Definition: glob.c:206
int k
Definition: otp-parser.c:70
static int dpi
Definition: pbmtolj.c:33
static struct Point current
Definition: picttoppm.c:134
#define fp
static boolean abspage
Definition: ppagelist.c:30
integer pagenum
Definition: pscolor.c:30
#define uint32_t
Definition: stdint.in.h:168
Definition: tables.h:434
char * name
Definition: dvipng.h:134
struct page_list * pagelistp
Definition: dvipng.h:139
struct font_num * fontnump
Definition: dvipng.h:138
uint32_t num
Definition: dvipng.h:130
int type
Definition: dvipng.h:128
time_t mtime
Definition: dvipng.h:137
int32_t conv
Definition: dvipng.h:131
FILE * filep
Definition: dvipng.h:136
char * outname
Definition: dvipng.h:135
uint32_t mag
Definition: dvipng.h:130
uint32_t flags
Definition: dvipng.h:142
uint32_t den
Definition: dvipng.h:130
int32_t count[11]
Definition: dvipng.h:158
struct page_list * next
Definition: dvipng.h:156
int offset
Definition: dvipng.h:157
Definition: mendex.h:14
#define FILE
Definition: t1stdio.h:34
*job_name strlen((char *) job_name) - 4)