305 lines
6.8 KiB
C
305 lines
6.8 KiB
C
/*
|
|
* parse.c
|
|
*
|
|
* This file is part of the ttf2pk package.
|
|
*
|
|
* Copyright 1997-1999 by
|
|
* Frederic Loyer <loyer@ensta.fr>
|
|
* Werner Lemberg <wl@gnu.org>
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stddef.h> /* for size_t */
|
|
#include <ctype.h>
|
|
#include <string.h>
|
|
|
|
#include "ttf2tfm.h"
|
|
#include "errormsg.h"
|
|
#include "newobj.h"
|
|
#include "ligkern.h"
|
|
#include "texenc.h"
|
|
#include "parse.h"
|
|
#include "filesrch.h"
|
|
|
|
|
|
/*
|
|
* Here we get a token from the encoding file. We parse just as much
|
|
* PostScript as we expect to find in an encoding file. We allow
|
|
* commented lines and names like 0, .notdef, _foo_. We do not allow
|
|
* //abc.
|
|
*
|
|
* `bufferp' is a pointer to the current line; the offset of the beginning
|
|
* of the token to be parsed relative to `bufferp' will be returned in
|
|
* `offsetp'. On the first call of gettoken() `init' must be set to 1 and
|
|
* to 0 on the following calls.
|
|
*
|
|
* If `ignoreligkern' is `True', no LIGKERN data will be extracted from the
|
|
* encoding file.
|
|
*
|
|
* Don't modify `bufferp'!
|
|
*
|
|
* The memory management of `bufferp' will be done by gettoken() itself;
|
|
* nevertheless, it returns a pointer to the current token which should be
|
|
* freed after it has been used.
|
|
*/
|
|
|
|
static char *
|
|
gettoken(char **bufferp, size_t *offsetp, FILE *f, Font *fnt,
|
|
Boolean ignoreligkern, Boolean init)
|
|
{
|
|
char *p, *q;
|
|
char tempchar;
|
|
static char *curp;
|
|
|
|
|
|
if (init)
|
|
curp = NULL;
|
|
|
|
while (1)
|
|
{
|
|
while (curp == NULL || *curp == '\0')
|
|
{
|
|
if (*bufferp)
|
|
free(*bufferp);
|
|
|
|
if (getline(bufferp, f) == False)
|
|
oops("Premature end in encoding file.");
|
|
|
|
curp = *bufferp;
|
|
|
|
for (p = *bufferp; *p; p++)
|
|
if (*p == '%')
|
|
{
|
|
if (ignoreligkern == False)
|
|
checkligkern(p, fnt);
|
|
*p = '\0';
|
|
break;
|
|
}
|
|
}
|
|
|
|
while (isspace(*curp))
|
|
curp++;
|
|
|
|
*offsetp = curp - *bufferp;
|
|
|
|
if (*curp)
|
|
{
|
|
if (*curp == '[' || *curp == ']' ||
|
|
*curp == '{' || *curp == '}')
|
|
q = curp++;
|
|
else if (*curp == '/' ||
|
|
*curp == '-' || *curp == '_' || *curp == '.' ||
|
|
('0' <= *curp && *curp <= '9') ||
|
|
('a' <= *curp && *curp <= 'z') ||
|
|
('A' <= *curp && *curp <= 'Z'))
|
|
{
|
|
q = curp++;
|
|
while (*curp == '-' || *curp == '_' || *curp == '.' ||
|
|
('0' <= *curp && *curp <= '9') ||
|
|
('a' <= *curp && *curp <= 'z') ||
|
|
('A' <= *curp && *curp <= 'Z'))
|
|
curp++;
|
|
}
|
|
else
|
|
q = curp;
|
|
|
|
tempchar = *curp;
|
|
*curp = '\0';
|
|
p = newstring(q);
|
|
*curp = tempchar;
|
|
return p;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* This routine reads in an encoding file, given the name. It returns
|
|
* the final total structure. It performs a number of consistency checks.
|
|
*/
|
|
|
|
encoding *
|
|
readencoding(char **enc, Font *fnt, Boolean ignoreligkern)
|
|
{
|
|
char *real_encname;
|
|
FILE *enc_file;
|
|
char *p, *q, c;
|
|
char *buffer;
|
|
char numbuf[9];
|
|
size_t offset;
|
|
int i;
|
|
long l;
|
|
encoding *e = (encoding *)mymalloc(sizeof (encoding));
|
|
|
|
|
|
if (enc && *enc)
|
|
{
|
|
real_encname = TeX_search_encoding_file(enc);
|
|
if (!real_encname)
|
|
oops("Cannot find encoding file `%s'.", *enc);
|
|
|
|
enc_file = fopen(real_encname, "rt");
|
|
if (enc_file == NULL)
|
|
oops("Cannot open encoding file `%s'.", real_encname);
|
|
|
|
buffer = NULL;
|
|
p = gettoken(&buffer, &offset, enc_file, fnt, ignoreligkern, True);
|
|
if (*p != '/' || p[1] == '\0')
|
|
boops(buffer, offset,
|
|
"First token in encoding must be literal encoding name.");
|
|
e->name = newstring(p + 1);
|
|
free(p);
|
|
|
|
p = gettoken(&buffer, &offset, enc_file, fnt, ignoreligkern, False);
|
|
if (strcmp(p, "["))
|
|
boops(buffer, offset,
|
|
"Second token in encoding must be mark ([) token.");
|
|
free(p);
|
|
|
|
for (i = 0; i < 256; i++)
|
|
{
|
|
p = gettoken(&buffer, &offset, enc_file, fnt, ignoreligkern, False);
|
|
if (*p != '/' || p[1] == 0)
|
|
boops(buffer, offset,
|
|
"Tokens 3 to 257 in encoding must be literal names.");
|
|
|
|
/* now we test for a generic code point resp. glyph index value */
|
|
|
|
c = p[2];
|
|
if (p[1] == '.' && (c == 'c' || c == 'g') && '0' <= p[3] && p[3] <= '9')
|
|
{
|
|
l = strtol(p + 3, &q, 0);
|
|
if (*q != '\0' || l < 0 || l > 0xFFFF)
|
|
boops(buffer, offset, "Invalid encoding token.");
|
|
sprintf(numbuf, ".%c0x%x", c, (unsigned int)l);
|
|
e->vec[i] = newstring(numbuf);
|
|
}
|
|
else
|
|
e->vec[i] = newstring(p + 1);
|
|
|
|
free(p);
|
|
}
|
|
|
|
p = gettoken(&buffer, &offset, enc_file, fnt, ignoreligkern, False);
|
|
if (strcmp(p, "]"))
|
|
boops(buffer, offset,
|
|
"Token 258 in encoding must be make-array (]).");
|
|
free(p);
|
|
|
|
while (getline(&buffer, enc_file))
|
|
{
|
|
for (p = buffer; *p; p++)
|
|
if (*p == '%')
|
|
{
|
|
if (ignoreligkern == False)
|
|
checkligkern(p, fnt);
|
|
*p = '\0';
|
|
break;
|
|
}
|
|
}
|
|
|
|
fclose(enc_file);
|
|
|
|
if (ignoreligkern == False && fnt->sawligkern == False)
|
|
getligkerndefaults(fnt);
|
|
}
|
|
else
|
|
{
|
|
if (ignoreligkern == False)
|
|
{
|
|
e = &staticencoding;
|
|
getligkerndefaults(fnt);
|
|
}
|
|
else
|
|
e = NULL;
|
|
}
|
|
|
|
return e;
|
|
}
|
|
|
|
|
|
/*
|
|
* We scan a glyph replacement file.
|
|
* `%' is the comment character.
|
|
*/
|
|
|
|
void
|
|
get_replacements(Font *fnt)
|
|
{
|
|
char *real_replacement_name;
|
|
FILE *replacement_file;
|
|
char *buffer = NULL, *oldbuffer = NULL;
|
|
char *p;
|
|
char *old_name, *new_name;
|
|
stringlist *sl;
|
|
|
|
|
|
if (!fnt->replacementname)
|
|
return;
|
|
|
|
real_replacement_name = TeX_search_replacement_file(&fnt->replacementname);
|
|
if (!real_replacement_name)
|
|
oops("Cannot find replacement file `%s'.", fnt->replacementname);
|
|
|
|
replacement_file = fopen(real_replacement_name, "rt");
|
|
if (replacement_file == NULL)
|
|
oops("Cannot open replacement file `%s'.", real_replacement_name);
|
|
|
|
while (getline(&buffer, replacement_file))
|
|
{
|
|
for (p = buffer; *p; p++)
|
|
if (*p == '%')
|
|
{
|
|
*p = '\0';
|
|
break;
|
|
}
|
|
|
|
if (oldbuffer)
|
|
free(oldbuffer);
|
|
oldbuffer = newstring(buffer);
|
|
|
|
p = buffer;
|
|
|
|
while (isspace(*p))
|
|
p++;
|
|
if (!*p)
|
|
continue;
|
|
|
|
old_name = p;
|
|
|
|
while (*p && !isspace(*p))
|
|
p++;
|
|
if (*p)
|
|
*p++ = '\0';
|
|
|
|
while (*p && isspace(*p))
|
|
p++;
|
|
if (!*p)
|
|
boops(oldbuffer, old_name - oldbuffer, "Replacement glyph missing.");
|
|
|
|
new_name = p;
|
|
|
|
while (*p && !isspace(*p))
|
|
p++;
|
|
if (*p)
|
|
*p++ = '\0';
|
|
|
|
while (*p && isspace(*p))
|
|
p++;
|
|
if (*p)
|
|
boops(oldbuffer, p - oldbuffer, "Invalid replacement syntax.");
|
|
|
|
sl = newstringlist();
|
|
sl->new_name = newstring(new_name);
|
|
sl->old_name = newstring(old_name);
|
|
sl->next = fnt->replacements;
|
|
fnt->replacements = sl;
|
|
}
|
|
|
|
fclose(replacement_file);
|
|
}
|
|
|
|
|
|
/* end */
|