home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume2 / mkfont < prev    next >
Encoding:
Internet Message Format  |  1991-08-07  |  41.8 KB

  1. From: sysad@tikal.teltone.com (Duane Hesser)
  2. Newsgroups: comp.sources.misc
  3. Subject: v02i084: mkfont/rdfont--compile and uncompile ditroff fonts
  4. Message-ID: <8804022315.AA28299@tikal.Teltone.COM>
  5. Date: 2 Apr 88 23:15:28 GMT
  6. Approved: allbery@ncoast.UUCP
  7.  
  8. comp.sources.misc: Volume 2, Issue 84
  9. Submitted-By: "Duane Hesser" <sysad@tikal.teltone.com>
  10. Archive-Name: mkfont
  11.  
  12. There are two complementary programs enclosed here.
  13. 'mkfont' duplicates the function of "makedev" to create binary
  14. font files, readable by ditroff, from ascii descriptions.
  15. 'rdfont' reverses the process, generating ascii descriptions
  16. form existing binary font files.  It's all in the README and
  17. man page.
  18. ------ cut here --------
  19. #!/bin/sh
  20. echo 'Start of MKFONT/RDFONT, part 01 of 01:'
  21. echo 'x - README'
  22. sed 's/^X//' > README << '/'
  23. XMkfont duplicates  the actions  (more or  less) of  the ATT  "makedev"
  24. Xprogram,  tp  produce  binary  font  files  for  ditroff,  from  ascii
  25. Xdescriptions for the fonts.   Rdfont will read  the binary font  files
  26. Xand produce an  ascii equivalent  (which may then  be re-compiled)  by
  27. Xmkfont.
  28. X
  29. XThese programs were written on a Pyramid 90x in the ucb universe,  and
  30. Xshould compile fairly  readily in  any BSD  environment; they've  been
  31. Xcompiled in the att  environment, and on a  Vax 750 under 4.3BSD  (but
  32. Xnot really tested  in those environments).   Check the  CFLAGS in  the
  33. XMakefile for SYS5.  There is also a cakefile, for those so inclined.
  34. XFor some systems, you may have to deal with the 3-argument open() calls.
  35. X
  36. XThe programs were written  after Pyramid supplied  ditroff with an  OS
  37. Xupgrade,  but  didn't  supply  makedev.    "makedev"  has  since  been
  38. Xsupplied, and mkfont checked against it.
  39. X
  40. XMkfont has  been used  to compile  Postscript fonts  from  description
  41. Xfiles posted to USENET in May of 1986 by Stephen Frede at U of NSW  in
  42. XSydney, Australia--you  should  be able  to  find them  in  a  sources
  43. Xarchive somewhere, if you need them.
  44. X
  45. XI am the author of  these programs, and I  submit them for public  use
  46. Xwithout restriction.
  47. X
  48. XCAVEATS
  49. XThe binary font  files produced  by mkfont will  differ slightly  from
  50. Xthose produced by makedev if there are duplicate entries in the  width
  51. Xtable, unless you use the '-c' option to mkfont (see the man page  for
  52. Xa little more info).
  53. X
  54. XIf you use  these to produce  Postscript font files,  be aware of  the
  55. Xstandard ditroff limit of 10 fonts (enforced by core dump).  I believe
  56. Xpatches to  fix  this  and  other bugs  are  in  the  USENET  archives
  57. Xsomewhere.   For those  of you  with  Pyramids, RTOC  can send  you  a
  58. Xversion which will  handle up to  25 files; otherwise  you'll have  to
  59. Xpick and  chose.    NOTE:  mkfont will  compile  them  fine  (as  will
  60. Xmakedev), but ditroff won't like 'em.
  61. X
  62. X
  63. XDuane H. Hesser
  64. Xdhh@teltone.com
  65. /
  66. echo 'x - Makefile'
  67. sed 's/^X//' > Makefile << '/'
  68. X#for S5 uncomment next line
  69. X# CFLAGS=-DSYS5
  70. X
  71. XRDSRC=    readdesc.c rdfont.c strsave.c
  72. XRDOBJ=    readdesc.o rdfont.o strsave.o
  73. XMKSRC=    makedesc.c mkfont.c nextword.c strsave.c
  74. XMKOBJ=    makedesc.o mkfont.o nextword.o strsave.o
  75. X
  76. X
  77. Xall: mkfont rdfont
  78. X
  79. Xmkfont:    ${MKOBJ}
  80. X    cc -o mkfont -O ${MKOBJ}
  81. X
  82. Xrdfont:    ${RDOBJ}
  83. X    cc -o rdfont -O ${RDOBJ}
  84. X
  85. Xrdfont.o:    rdfont.c font.h
  86. Xreaddesc.o:    readdesc.c  dev.h
  87. X
  88. Xmkfont.o:    mkfont.c font.h
  89. Xmakedesc.o:    makedesc.c  dev.h
  90. X
  91. Xclean:
  92. X    rm -f *.o mkfont rdfont
  93. X
  94. Xlint:
  95. X    lint -phbvac dev.h font.h ${MKSRC} > lint.mkfont
  96. X    lint -phbvac dev.h font.h ${RDSRC} > lint.rdfont
  97. /
  98. echo 'x - Cakefile'
  99. sed 's/^X//' > Cakefile << '/'
  100. X#include "C"
  101. X#include "System"
  102. /
  103. echo 'x - Conf'
  104. sed 's/^X//' > Conf << '/'
  105. Xmkfont makedesc mkfont strsave nextword
  106. Xrdfont readdesc rdfont strsave nextword
  107. /
  108. echo 'x - mkfont.p'
  109. sed 's/^X//' > mkfont.p << '/'
  110. X.TH MKFONT  1-P
  111. X.SH NAME
  112. Xmkfont,rdfont \- create/read ditroff font files
  113. X.SH SYNOPSIS
  114. X.br
  115. X.B mkfont
  116. X.I \-c
  117. X[DESC]
  118. X.br
  119. X.B rdfont
  120. X[DESC.out]
  121. X.SH DESCRIPTION
  122. X.PP
  123. X.I Mkfont
  124. Xreads ascii format font description files and creates binary format
  125. Xfiles usable by
  126. X.I ditroff.
  127. XThe format of the ascii files may be guessed reasonably closely by
  128. Xreading \fCfont\fP(5) and \fCtroff\fP(5).
  129. XAlternatively, if you have existing fonts, you may run
  130. X.I rdfont
  131. Xon them to produce their ascii equivalents (which you may then
  132. Xmodify, if you like, and re-compile with \fImkfont\fP).
  133. XThe produced binary files are named by the input files suffixed with
  134. X.I .out.
  135. X.I Ditroff
  136. Xexpects the font description file to be named
  137. X.I DESC.out,
  138. Xso \fImkfont\fP expects an ascii file named \fIDESC\fP in the
  139. Xcurrent directory if no arguments are given; otherwise, the name
  140. Xof the description file must be given as argument.
  141. XThe \fI-c\fP flag causes the binary files produced to be more
  142. Xnearly compatible with those produced by the ATT \fImakedev\fP
  143. Xprogram (\fImakedev\fP does not make duplicate width table entries
  144. Xin the binary file for characters whose width is given by double
  145. Xquotes in the ascii file; \fImkfont\fP does, unless \fI-c\fP is
  146. Xgiven).
  147. X.PP
  148. X.I Rdfont
  149. Xexamines a binary format font set and produces a set of ascii files
  150. Xwhich describe them.  The ascii files are in a form suitable for
  151. Xre-compiling with \fImkfont\fP.
  152. XIf no arguments are given, a description file named \fIDESC.out\fP
  153. Xis expected.  An alternate description file name may be given as
  154. Xargument.
  155. XThe produced files are named by replacing the \fI.out\fP extensions
  156. Xof the input files by \fI.new\fP, to avoid overwriting existing
  157. Xdescription files.  If these files are to be re-compiled, the
  158. Xextensions should be removed.
  159. X.
  160. X.SH DIAGNOSTICS
  161. X.PP
  162. X.SH BUGS
  163. X.PP
  164. X.I Mkfont
  165. Xdoes not do much checking on the validity of the font, although it
  166. Xcould do so.
  167. X.I Rdfont
  168. Xwrites a few information items to the ascii file as comment lines.
  169. XThat's not a bug, but it does make comparison of originals and
  170. Xduplicates a bit (not muuch) harder.
  171. X.SH AUTHOR
  172. X.br
  173. XDuane H. Hesser
  174. X.br
  175. XTeltone Corporation
  176. /
  177. echo 'x - dev.h'
  178. sed 's/^X//' > dev.h << '/'
  179. X/*
  180. X * $Header: dev.h,v 1.1 87/10/23 19:08:07 sysad Exp $
  181. X */
  182. X
  183. X/*
  184. X * $Log:    dev.h,v $
  185. X * Revision 1.1  87/10/23  19:08:07  sysad
  186. X * Initial revision
  187. X * 
  188. X * 
  189. X */
  190. X
  191. X struct dev {
  192. X    unsigned short filesize;
  193. X    short res;
  194. X    short hor;
  195. X    short vert;
  196. X    short unitwidth;
  197. X    short nfonts;
  198. X    short nsizes;
  199. X    short sizescale;
  200. X    short paperwidth;
  201. X    short paperlength;
  202. X    short nchtab;
  203. X    short lchname;
  204. X    short biggestfont;
  205. X    short spare;
  206. X};
  207. /
  208. echo 'x - font.h'
  209. sed 's/^X//' > font.h << '/'
  210. X/*
  211. X * $Header: font.h,v 1.1 87/10/23 19:08:08 sysad Exp $
  212. X */
  213. X
  214. X/*
  215. X * $Log:    font.h,v $
  216. X * Revision 1.1  87/10/23  19:08:08  sysad
  217. X * Initial revision
  218. X * 
  219. X * 
  220. X */
  221. X
  222. Xstruct Font {
  223. X    char nwfont;
  224. X    char specfont;
  225. X    char ligfont;
  226. X    char pad;
  227. X    char namefont[10];
  228. X    char intname[10];
  229. X};
  230. X
  231. X#define    LIG_FF    01
  232. X#define    LIG_FI    02
  233. X#define    LIG_FL    04
  234. X#define    LIG_FFI    010
  235. X#define    LIG_FFL    020
  236. /
  237. echo 'x - makedesc.c'
  238. sed 's/^X//' > makedesc.c << '/'
  239. Xstatic char *RCSid = "$Header: makedesc.c,v 1.1 87/10/23 19:08:09 sysad Exp $";
  240. X
  241. X/* Read an ascii description of a ditroff font and create the         */
  242. X/* corresponding binary font files                                    */
  243. X
  244. X
  245. X/*
  246. X * $Log:    makedesc.c,v $
  247. X * Revision 1.1  87/10/23  19:08:09  sysad
  248. X * Initial revision
  249. X * 
  250. X * 
  251. X */
  252. X
  253. X#include <stdio.h>
  254. X#include <sys/file.h>
  255. X#include "dev.h"
  256. X
  257. X#define    SHORT    0xffff
  258. X#define    MAXP    128        /* allocate space for point sizes in MAXP chunks */
  259. Xint compat = 0;        /* compatibility with att "makedev"; duplicate "width"
  260. X                     * entries are re-used if this is non-zero.
  261. X                     */
  262. Xchar *Progname;
  263. Xstruct dev dev;
  264. Xextern char *malloc(),*nextword(),*savestr();
  265. Xextern char **font_names(),*fgets();
  266. Xextern FILE *fopen();
  267. Xextern short *p_sizes();
  268. X
  269. Xmain(argc,argv)
  270. Xint argc;
  271. Xchar **argv;
  272. X{
  273. X    FILE *inptr;
  274. X    int fdout,nchtab,lchname,i,fsize,biggestfont;
  275. X    long fontf_start;
  276. X    short *point_list,*funny_ind;
  277. X    char *funny_chars;
  278. X    char **font_list;
  279. X    char mybuf[1024];
  280. X    char *str,*descfile;
  281. X
  282. X    Progname = argv[0];
  283. X    ++argv; --argc;
  284. X
  285. X    if(strcmp(*argv,"-c") == 0)
  286. X    {
  287. X        ++compat;
  288. X        ++argv;
  289. X        --argc;
  290. X    }
  291. X    if(argc == 0)
  292. X    {
  293. X        descfile = "DESC";
  294. X    }
  295. X    else if(argc == 1)
  296. X    {
  297. X        descfile = argv[0];
  298. X    }
  299. X    else
  300. X    {
  301. X        fprintf(stderr,"usage: %s [-c] [descfile]\n",Progname);
  302. X        exit(1);
  303. X    }
  304. X
  305. X    if((inptr = fopen(descfile,"r")) == (FILE *)0)
  306. X    {
  307. X        fprintf(stderr,"%s: can't open %s\n",Progname,descfile);
  308. X        exit(2);
  309. X    }
  310. X    sprintf(mybuf,"%s.out",descfile);
  311. X    if((fdout = open(mybuf,O_CREAT | O_WRONLY,0644)) < 0)
  312. X    {
  313. X        fprintf(stderr,"%s: can't create %s\n",Progname,mybuf);
  314. X        exit(2);
  315. X    }
  316. X    dev.filesize = (short)0;
  317. X    dev.sizescale = (short)1;
  318. X    biggestfont = 0;
  319. X    dev.spare = (short)0;
  320. X    /* Build the dev structure first */
  321. X    while(fgets(mybuf,1024,inptr))
  322. X    {
  323. Xstart:    /* we come back here if we read ahead in a font_names() */
  324. X        if(!*mybuf || (*mybuf == '#'))
  325. X            continue;
  326. X        nextword("");    /* reset to beginning of line */
  327. X        /* printf("line = %s\n",mybuf); */
  328. X        str = nextword(mybuf);
  329. X        if(strcmp(str,"charset") == 0)
  330. X            break;
  331. X        if(strcmp(str,"res") == 0)
  332. X            dev.res = (short)atoi(nextword(mybuf));
  333. X        else if(strcmp(str,"hor") == 0)
  334. X            dev.hor = (short)atoi(nextword(mybuf));
  335. X        else if(strcmp(str,"vert") == 0)
  336. X            dev.vert = (short)atoi(nextword(mybuf));
  337. X        else if(strcmp(str,"unitwidth") == 0)
  338. X            dev.unitwidth = (short)atoi(nextword(mybuf));
  339. X        else if(strcmp(str,"sizescale") == 0)
  340. X            dev.sizescale = (short)atoi(nextword(mybuf));
  341. X        else if(strcmp(str,"paperwidth") == 0)
  342. X            dev.paperwidth = (short)atoi(nextword(mybuf));
  343. X        else if(strcmp(str,"paperlength") == 0)
  344. X            dev.paperlength = (short)atoi(nextword(mybuf));
  345. X        else if(strcmp(str,"biggestfont") == 0)
  346. X        {
  347. X            biggestfont = atoi(nextword(mybuf));
  348. X            dev.biggestfont = (short)biggestfont;
  349. X        }
  350. X        else if(strcmp(str,"sizes") == 0)
  351. X        {
  352. X            /* accumulate the list of legal point sizes */
  353. X            point_list = p_sizes(inptr,mybuf,&dev);
  354. X        }
  355. X        else if(strcmp(str,"fonts") == 0)
  356. X        {
  357. X            dev.nfonts = (short)atoi(nextword(mybuf));
  358. X            font_list = font_names(inptr,mybuf,dev.nfonts);
  359. X            goto start;
  360. X        }
  361. X    }
  362. X    nextword("");
  363. X    /* Next comes the funny index table and the character strings; read
  364. X     * the description and stuff the information into the binary format 
  365. X     * tables.
  366. X     */
  367. X    if(fgets(mybuf,1024,inptr) == (char *)0)
  368. X    {
  369. X        fprintf(stderr,"%s: no funny char strings table\n",Progname);
  370. X        exit(1);
  371. X    }
  372. X    nchtab = get_funny(inptr,mybuf,&funny_ind,&funny_chars,&lchname);
  373. X    dev.nchtab = (short)nchtab;
  374. X    dev.lchname = (short)lchname;
  375. X
  376. X    /* We don't have enough information yet to write the dev structure
  377. X     * (don't know how many fonts, or their names...).  We do know how
  378. X     * big it is, and how long the description tables are, so we seek
  379. X     * past all that stuff andd write the font descriptions first.
  380. X     * Later, we'll go back and write the stuff we skipped over.
  381. X     */
  382. X    fontf_start = (long)(sizeof(dev) + ((dev.nsizes +1) * sizeof(short))
  383. X                    + (nchtab * sizeof(short)) + lchname);
  384. X    (void)lseek(fdout,fontf_start,0);
  385. X
  386. X    /* Read the font files, and write the binary equivalents */
  387. X    for(i = 0; i < (int)dev.nfonts; ++i)
  388. X    {
  389. X        fsize = do_font(font_list[i],funny_chars,funny_ind,nchtab,fdout);
  390. X        /* keep track of the biggest font */
  391. X        if(fsize > biggestfont)
  392. X            biggestfont = fsize;
  393. X    }
  394. X    dev.biggestfont = (short)(biggestfont & SHORT);
  395. X    dev.filesize = (unsigned short)(lseek(fdout,0L,2) - sizeof(dev));
  396. X    write_desc(fdout,&dev,point_list,funny_ind,funny_chars);
  397. X    exit(0);
  398. X}
  399. X
  400. X/* Read the point sizes list */
  401. X
  402. Xshort *
  403. Xp_sizes(inptr,buf,dev)
  404. XFILE *inptr;
  405. Xchar *buf;
  406. Xstruct dev *dev;
  407. X{
  408. X    short *pl,*ret;
  409. X    char *word,*realloc();
  410. X    int nwords = 0;
  411. X    int n;
  412. X
  413. X    /* allow for MAXP point sizes; we have to reallocate if we exceed that */
  414. X    ret = pl = (short *)malloc((unsigned)(MAXP * sizeof(short)));
  415. X    if(!pl)
  416. X    {
  417. X        fprintf(stderr,"can't malloc space for psizes\n",Progname);
  418. X        exit(1);
  419. X    }
  420. X    n = 1;
  421. X    while((word = nextword(buf)) || fgets(buf,1024,inptr))
  422. X    {
  423. X        if(!word)
  424. X        {
  425. X            nextword("");
  426. X            word = nextword(buf);
  427. X        }
  428. X        if(!word)    /* ran out of words this line, had to fgets more */
  429. X        {
  430. X            nextword("");
  431. X            if(fgets(buf,1024,inptr))
  432. X                word = nextword(buf);
  433. X            else
  434. X            {
  435. X                *buf = '\0';
  436. X                break;
  437. X            }
  438. X        }
  439. X        nwords++;
  440. X        if(nwords >= MAXP)
  441. X        {
  442. X            /* Oops! ran out os space; get more */
  443. X            ret = (short *)realloc((char *)ret,(unsigned)(MAXP * ++n * sizeof(short)));
  444. X            pl = &ret[nwords];    /* could have moved */
  445. X        }
  446. X        *pl = (short)atoi(word);
  447. X        if(*pl == (short)0)
  448. X            break;
  449. X        ++pl;
  450. X    }
  451. X    /* don't count the zero at the end */
  452. X    --nwords;
  453. X    dev->nsizes = (short)nwords;
  454. X    return(ret);
  455. X}
  456. X
  457. X/* Read and save the font names; return the list */
  458. X
  459. Xchar **
  460. Xfont_names(inptr,buf,nfonts)
  461. XFILE *inptr;
  462. Xchar *buf;
  463. Xshort nfonts;
  464. X{
  465. X    char **ret,**next;
  466. X    char *word;
  467. X    int nwords = 0;
  468. X
  469. X    ret = next = (char **)malloc((unsigned)((nfonts + 1) * sizeof(char *)));
  470. X
  471. X    while((word = nextword(buf)) || fgets(buf,1024,inptr))
  472. X    {
  473. X        if(!word)
  474. X        {
  475. X            nextword("");
  476. X            word = nextword(buf);
  477. X        }
  478. X        *next++ = savestr(word);
  479. X        if(++nwords >= (int)nfonts)
  480. X        {
  481. X            /* main() expects a new buffer */
  482. X            fgets(buf,1024,inptr);
  483. X            break;
  484. X        }
  485. X    }
  486. X    *next = (char *)0;
  487. X    if(nwords != (int)nfonts)
  488. X        printf("%s: warning; only got %d of %d font names\n",Progname,nwords,(int)nfonts);
  489. X    return(ret);
  490. X}
  491. X
  492. X
  493. X/* Read the special character strings, and set up the string table and
  494. X * the index into it.
  495. X */
  496. Xget_funny(inptr,mybuf,funny_ind,funny_chars,lchname)
  497. XFILE *inptr;
  498. Xchar *mybuf;
  499. Xshort **funny_ind;
  500. Xchar **funny_chars;
  501. Xint *lchname;
  502. X{
  503. X    char *fct;    /* funny char string table */
  504. X    short *fci; /* funny char index           */
  505. X    int i = 0;
  506. X    int lastp = 0;
  507. X    char *str;
  508. X
  509. X    /* allocate for 256 3-character strings (plus null)             */
  510. X    /* We should probably check for overflow, but I can't imagine a    */
  511. X    /* character set with more than 256 special chars (FLW)            */
  512. X
  513. X    *funny_chars = fct = malloc((unsigned)768);
  514. X    *funny_ind = fci = (short *)malloc((unsigned)(257 * sizeof(short)));
  515. X
  516. X    /* assume the strings start on a new line */
  517. X    fci[0] = (short)0;
  518. X    while((str = nextword(mybuf)) || fgets(mybuf,1024,inptr))
  519. X    {
  520. X        if(!str)
  521. X        {
  522. X            nextword("");
  523. X            str = nextword(mybuf);
  524. X            if(!str)
  525. X                continue;
  526. X        }
  527. X        (void)strcpy(fct + lastp,str);
  528. X        fci[i++] = (short)(lastp & SHORT);
  529. X        lastp += strlen(str) + 1;
  530. X        if(i > 256)
  531. X        {
  532. X            fprintf(stderr,"%s: too many special strings (> 256)\n",Progname);
  533. X            break;
  534. X        }
  535. X    }
  536. X    fci[i++] = (short)0;
  537. X    *lchname = lastp;
  538. X    return(i);
  539. X}
  540. X
  541. X/* Write out the dev structure,the sizes table, and the funny char tables */
  542. Xwrite_desc(fdout,dev,point_list,funny_ind,funny_chars)
  543. Xint fdout;
  544. Xstruct dev *dev;
  545. Xshort *point_list,*funny_ind;
  546. Xchar *funny_chars;
  547. X{
  548. X
  549. X    long l;
  550. X
  551. X    /* Seek back to the beginning of the file */
  552. X
  553. X    (void)lseek(fdout,0L,0);
  554. X
  555. X    /* dev structure */
  556. X    if(write(fdout,(char *)dev,sizeof(struct dev)) != sizeof(struct dev))
  557. X    {
  558. X        fprintf(stderr,"%s: write dev struct to description file failed\n",Progname);
  559. X        exit(1);
  560. X    }
  561. X
  562. X    /* point sizes table */
  563. X    if(write(fdout,(char *)point_list,(int)(dev->nsizes +1) * 2) != (int)(dev->nsizes + 1) * 2)
  564. X    {
  565. X        fprintf(stderr,"%s: write size list to description file failed\n",Progname);
  566. X        exit(1);
  567. X    }
  568. X
  569. X    /* table of indexes into special char strings */
  570. X    if(write(fdout,(char *)funny_ind,(int)(dev->nchtab * 2)) != (int)(dev->nchtab * 2))
  571. X    {
  572. X        fprintf(stderr,"%s: write index list to description file failed\n",Progname);
  573. X        exit(1);
  574. X    }
  575. X
  576. X    /* special char strings */
  577. X    if(write(fdout,funny_chars,(int)(dev->lchname)) != (int)(dev->lchname))
  578. X    {
  579. X        fprintf(stderr,"%s: write funny char strings to description file failed\n",Progname);
  580. X        exit(1);
  581. X    }
  582. X    l = lseek(fdout,0L,1);
  583. X}
  584. /
  585. echo 'x - mkfont.c'
  586. sed 's/^X//' > mkfont.c << '/'
  587. Xstatic char *RCSid = "$Header: mkfont.c,v 1.1 87/10/23 19:08:10 sysad Exp $";
  588. X
  589. X/*
  590. X * $Log:    mkfont.c,v $
  591. X * Revision 1.1  87/10/23  19:08:10  sysad
  592. X * Initial revision
  593. X * 
  594. X * 
  595. X */
  596. X
  597. X#include <stdio.h>
  598. X#include <sys/file.h>
  599. X#include "font.h"
  600. X#ifdef SYS5
  601. X#define    bzero(a,b)    memset(a,0,b)
  602. X#endif
  603. X
  604. X#define NCHARMAX    256            /* max chars in font */
  605. X#define    NASC        96            /* number of printable ascii chars */
  606. X#define    BYTE        0xff        /* mask */
  607. X#define    SHORT        0xffff        /* mask */
  608. X
  609. Xextern char *malloc(),*savestr(),*nextword(),*fgets();
  610. Xextern FILE *fopen();
  611. Xextern char *Progname;
  612. Xextern int compat;
  613. X
  614. X/* Read the ascii font description files, and write the binary files. */
  615. X/*                                                                    */
  616. X
  617. Xdo_font(fontname,funny_chars,funny_ind,nchtab,fdout)
  618. Xchar *fontname,*funny_chars;
  619. Xshort *funny_ind;
  620. Xint nchtab,fdout;
  621. X{
  622. X    FILE *src;
  623. X    char mybuf[256];
  624. X    /* allocate them just once */
  625. X    static char *width,*kern,*code,*fontindex = (char *)0;
  626. X    
  627. X    struct Font font;
  628. X    char *word;
  629. X    int dest,spacewidth,nwfont,indx;
  630. X
  631. X    /* The ascii source file, named by the font name. */
  632. X    if((src = fopen(fontname,"r")) == (FILE *)0)
  633. X    {
  634. X        fprintf(stderr,"%s: can't open font %s\n",Progname,fontname);
  635. X        exit(1);
  636. X    }
  637. X
  638. X    /* create the binary font face file */
  639. X    sprintf(mybuf,"%s.out",fontname);
  640. X    if((dest = open(mybuf,O_CREAT | O_WRONLY,0644)) < 0)
  641. X    {
  642. X        fprintf(stderr,"%s: can't create font %s output file\n",Progname,mybuf);
  643. X        exit(1);
  644. X    }
  645. X    fontindex = width = kern = code = (char *)0;
  646. X
  647. X    spacewidth = 0;
  648. X    font.ligfont = (char)0;
  649. X
  650. X    /* Build the font structure.                                      */
  651. X
  652. X    while(fgets(mybuf,256,src))
  653. X    {
  654. X        word = nextword("");    /* reset to beginning of line */
  655. X        word = nextword(mybuf);
  656. X        if(!word || !*word || (*word == '#'))
  657. X            continue;
  658. X        if(strcmp(word,"charset") == 0)
  659. X            break;
  660. X        if(strcmp(word,"name") == 0)
  661. X            strncpy(font.namefont,nextword(mybuf),10);
  662. X        else if(strcmp(word,"internalname") == 0)
  663. X            strncpy(font.intname,nextword(mybuf),10);
  664. X        else if(strcmp(word,"spacewidth") == 0)
  665. X            spacewidth = atoi(nextword(mybuf)) & BYTE;
  666. X        else if(strcmp(word,"special") == 0)
  667. X            font.specfont =  0x01;
  668. X        else if(strcmp(word,"ligatures") == 0)
  669. X        {
  670. X            while(word = nextword(mybuf))
  671. X            {
  672. X                if(*word == '0')
  673. X                    break;
  674. X                else if(strcmp(word,"fi") == 0)
  675. X                    font.ligfont |= LIG_FI;
  676. X                else if(strcmp(word,"fl") == 0)
  677. X                    font.ligfont |= LIG_FL;
  678. X                else if(strcmp(word,"ff") == 0)
  679. X                    font.ligfont |= LIG_FF;
  680. X                else if(strcmp(word,"ffi") == 0)
  681. X                    font.ligfont |= LIG_FFI;
  682. X                else if(strcmp(word,"ffl") == 0)
  683. X                    font.ligfont |= LIG_FFL;
  684. X            }
  685. X        }
  686. X    }
  687. X
  688. X    /* The next 4 tables are allocated just once, big enough for any font,
  689. X     * then re-used for each font face.
  690. X     */
  691. X
  692. X    if(fontindex == (char *)0)
  693. X    {
  694. X        fontindex = malloc((unsigned)(NASC + nchtab));
  695. X        if(fontindex == (char *)0)
  696. X        {
  697. X            fprintf(stderr,"%s: can't malloc font index table\n",Progname);
  698. X            exit(1);
  699. X        }
  700. X    }
  701. X
  702. X    if(width == (char *)0)
  703. X    {
  704. X        width = malloc(NCHARMAX);
  705. X        if(width == (char *)0)
  706. X        {
  707. X            free(fontindex);
  708. X            fontindex = (char *)0;
  709. X            fprintf(stderr,"%s: can't malloc font widths table\n",Progname);
  710. X            exit(1);
  711. X        }
  712. X    }
  713. X    if(kern == (char *)0)
  714. X    {
  715. X        kern = malloc(NCHARMAX);
  716. X        if(kern == (char *)0)
  717. X        {
  718. X            free(width);
  719. X            free(fontindex);
  720. X            fontindex = (char *)0;
  721. X            width = (char *)0;
  722. X            fprintf(stderr,"%s: can't malloc font kern table\n",Progname);
  723. X            exit(1);
  724. X        }
  725. X    }
  726. X
  727. X    if(code == (char *)0)
  728. X    {
  729. X        code = malloc(NCHARMAX);
  730. X        if(code == (char *)0)
  731. X        {
  732. X            free(width);
  733. X            free(kern);
  734. X            free(fontindex);
  735. X            fontindex = (char *)0;
  736. X            width = (char *)0;
  737. X            kern = (char *)0;
  738. X            fprintf(stderr,"%s: can't malloc font code table\n",Progname);
  739. X            exit(1);
  740. X        }
  741. X    }
  742. X
  743. X    /* clear them */
  744. X    bzero(width,NCHARMAX);
  745. X    bzero(kern,NCHARMAX);
  746. X    bzero(code,NCHARMAX);
  747. X    bzero(fontindex,NASC + nchtab);
  748. X
  749. X    /* first width entry is width of space if non-zero */
  750. X    width[0] = (char)(spacewidth & BYTE);
  751. X    kern[0] = '\0';
  752. X    code[0] = '\0';
  753. X
  754. X    nwfont = 1;
  755. X    
  756. X    /* decode the character set info and stuff the width, kern, code
  757. X     * tables, building the font index table as we go
  758. X     */
  759. X    while(fgets(mybuf,256,src))
  760. X    {
  761. X        nextword("");    /* reset to beginning of line */
  762. X        word = nextword(mybuf);
  763. X        if(!word || !*word)
  764. X            continue;
  765. X        if(strlen(word) == 1)
  766. X            indx = (*word & BYTE) - 32;        /* printable ascii */
  767. X        else
  768. X            indx = spcl(word,funny_chars,funny_ind,nchtab); /* troff special chars */
  769. X        if(indx < 0)
  770. X        {
  771. X            fprintf(stderr,"%s: special string \"%s\" is not defined in desc\n",Progname,word);
  772. X            fprintf(stderr,"...skipping\n");
  773. X            continue;
  774. X        }
  775. X
  776. X        /* check for repeat characters ( " in width column) */
  777. X        word = nextword(mybuf);
  778. X
  779. X        if(*word == '"')
  780. X        {
  781. X            /* It appears that att's "makefont" doesn't make a new
  782. X             * width entry for dups--it just reuses the earlier one.
  783. X             * It would be much easier for "rdfont" to decode these
  784. X             * things if we just made a duplicate entry, but for
  785. X             * compatibility with "makefont" (as determined by examination
  786. X             * of compiled fonts delivered to us)...
  787. X             */
  788. X            if(!compat)
  789. X            {
  790. X                /* make a separate width entry for each duplicate */
  791. X                width[nwfont] = width[nwfont - 1];
  792. X                kern[nwfont] = kern[nwfont - 1];
  793. X                code[nwfont] = code[nwfont - 1];
  794. X                fontindex[indx] = (char)(nwfont & BYTE);
  795. X                nwfont++;
  796. X            }
  797. X            fontindex[indx] = (char)((nwfont - 1) & BYTE);
  798. X            continue;
  799. X        }
  800. X        fontindex[indx] = (char)(nwfont & BYTE);
  801. X        width[nwfont] = (char)(atoi(word) & BYTE);
  802. X        word = nextword(mybuf);
  803. X        kern[nwfont] = (char)(atoi(word) & BYTE);
  804. X        word = nextword(mybuf);
  805. X        code[nwfont++] = (char)(atoo(word) & BYTE);
  806. X    }
  807. X
  808. X    fclose(src);
  809. X    font.nwfont = (short)(nwfont & BYTE);
  810. X    printf("%s: nwfont = %d\n",fontname,nwfont);
  811. X
  812. X
  813. X
  814. X    /* write the tables, first to the description file, then to the
  815. X     * individual font file.
  816. X     */
  817. X    if(write(fdout,(char *)&font,sizeof(struct Font)) != sizeof(struct Font))
  818. X    {
  819. X        fprintf(stderr,"%s: write font struct to description file failed\n",Progname);
  820. X        exit(1);
  821. X    }
  822. X    if(write(dest,(char *)&font,sizeof(struct Font)) != sizeof(struct Font))
  823. X    {
  824. X        fprintf(stderr,"%s: write font struct to font output file failed\n",Progname);
  825. X        exit(1);
  826. X    }
  827. X    if(write(fdout,width,nwfont) != nwfont)
  828. X    {
  829. X        fprintf(stderr,"%s: write width table to description file failed\n",Progname);
  830. X        exit(1);
  831. X    }
  832. X    if(write(dest,width,nwfont) != nwfont)
  833. X    {
  834. X        fprintf(stderr,"%s: write width table to font output file failed\n",Progname);
  835. X        exit(1);
  836. X    }
  837. X    if(write(fdout,kern,nwfont) != nwfont)
  838. X    {
  839. X        fprintf(stderr,"%s: write kern table to description file failed\n",Progname);
  840. X        exit(1);
  841. X    }
  842. X    if(write(dest,kern,nwfont) != nwfont)
  843. X    {
  844. X        fprintf(stderr,"%s: write kern table to font output file failed\n",Progname);
  845. X        exit(1);
  846. X    }
  847. X    if(write(fdout,code,nwfont) != nwfont)
  848. X    {
  849. X        fprintf(stderr,"%s: write code table to description file failed\n",Progname);
  850. X        exit(1);
  851. X    }
  852. X    if(write(dest,code,nwfont) != nwfont)
  853. X    {
  854. X        fprintf(stderr,"%s: write code table to font output file failed\n",Progname);
  855. X        exit(1);
  856. X    }
  857. X    if(write(fdout,fontindex,nchtab + NASC) != nchtab + NASC)
  858. X    {
  859. X        fprintf(stderr,"%s: write font index table to description file failed\n",Progname);
  860. X        exit(1);
  861. X    }
  862. X    if(write(dest,fontindex,nchtab + NASC) != nchtab + NASC)
  863. X    {
  864. X        fprintf(stderr,"%s: write font index table to font output file failed\n",Progname);
  865. X        exit(1);
  866. X    }
  867. X    close(dest);    /* done with this font file */
  868. X    return(nwfont);    /* the return is extraneous here */
  869. X}
  870. X
  871. X/* Find the font index of special character strings */
  872. X
  873. Xspcl(word,funny_chars,funny_ind,nchtab)
  874. Xchar *word,*funny_chars;
  875. Xshort *funny_ind;
  876. Xint nchtab;
  877. X{
  878. X    int i;
  879. X
  880. X    for(i = 0; i < nchtab; ++i)
  881. X    {    
  882. X        if(strcmp(word,funny_chars + (int)(funny_ind[i] & SHORT)) == 0)
  883. X            return(i + NASC);
  884. X    }
  885. X    return(-1);
  886. X}
  887. X
  888. X/* convert an octal string representation to an int */
  889. X
  890. Xatoo(str)
  891. Xchar *str;
  892. X{
  893. X    int i;
  894. X    /* cheat */
  895. X    sscanf(str,"%o",&i);
  896. X    return(i);
  897. X}
  898. /
  899. echo 'x - rdfont.c'
  900. sed 's/^X//' > rdfont.c << '/'
  901. Xstatic char *RCSid = "$Header: rdfont.c,v 1.1 87/10/23 19:08:13 sysad Exp $";
  902. X
  903. X/*
  904. X * $Log:    rdfont.c,v $
  905. X * Revision 1.1  87/10/23  19:08:13  sysad
  906. X * Initial revision
  907. X * 
  908. X * 
  909. X */
  910. X
  911. X#include <stdio.h>
  912. X#include "font.h"
  913. X
  914. X#ifdef SYS5
  915. X#define    bzero(a,b)    memset(a,0,b)
  916. X#endif
  917. X
  918. X#define    SHORT    0xffff        /* mask */
  919. X#define    HISHORT    0xffff0000    /* mask */
  920. X#define    BYTE    0xff        /* mask */
  921. X#define NASC    96            /* number of printable ascii characters */
  922. Xextern char *malloc(),*savestr(),*pr_font();
  923. Xextern char *Progname;
  924. Xextern int debugging;
  925. X
  926. Xchar *
  927. X/* Read a binary font face file */
  928. X
  929. Xrdfont(fd,nspec,funny_tab,funny_index)
  930. Xint fd,nspec;
  931. Xchar *funny_tab;
  932. Xshort *funny_index;
  933. X{
  934. X    char *widths;
  935. X    char *kerning;
  936. X    char *code;
  937. X    char *font_ind;
  938. X    char *fname;
  939. X    struct Font font;
  940. X    unsigned int nwidths;
  941. X    int i;
  942. X
  943. X    /* get the font info from the description file */
  944. X    if(read(fd,(char *)&font,sizeof(struct Font)) != sizeof(struct Font))
  945. X    {
  946. X        fprintf(stderr,"%s: can't read font info\n",Progname);
  947. X        return((char *)0);
  948. X    }
  949. X
  950. X    /* Allocate space for the tables */
  951. X    nwidths = font.nwfont & BYTE;
  952. X    widths = malloc(nwidths);
  953. X    if(!widths)
  954. X    {
  955. X        fprintf(stderr,"%s: can't malloc widths\n",Progname);
  956. X        return((char *)0);
  957. X    }
  958. X    kerning = malloc(nwidths);
  959. X    if(!kerning)
  960. X    {
  961. X        fprintf(stderr,"%s: can't malloc kerning\n",Progname);
  962. X        free(widths);
  963. X        return((char *)0);
  964. X    }
  965. X    code = malloc(nwidths);
  966. X    if(!code)
  967. X    {
  968. X        fprintf(stderr,"%s: can't malloc code\n",Progname);
  969. X        free(widths);
  970. X        free(kerning);
  971. X        return((char *)0);
  972. X    }
  973. X
  974. X    /* Read 'em in */
  975. X    if((i = read(fd,widths,nwidths)) != nwidths)
  976. X    {
  977. X        fprintf(stderr,"%s: read %d of %d widths \n",i,nwidths,Progname);
  978. X        free(widths);
  979. X        free(kerning);
  980. X        free(code);
  981. X        return((char *)0);
  982. X    }
  983. X    if((i = read(fd,kerning,nwidths)) != nwidths)
  984. X    {
  985. X        fprintf(stderr,"%s: read %d of %d kernings\n",i,nwidths,Progname);
  986. X        free(widths);
  987. X        free(kerning);
  988. X        free(code);
  989. X        return((char *)0);
  990. X    }
  991. X    if((i = read(fd,code,nwidths)) != nwidths)
  992. X    {
  993. X        fprintf(stderr,"%s: read %d of %d codes\n",i,nwidths,Progname);
  994. X        free(widths);
  995. X        free(kerning);
  996. X        free(code);
  997. X        return((char *)0);
  998. X    }
  999. X    font_ind = malloc(NASC + nspec);
  1000. X    if(!font_ind)
  1001. X    {
  1002. X        fprintf(stderr,"%s: malloc font_ind failed\n",Progname);
  1003. X        free(widths);
  1004. X        free(kerning);
  1005. X        free(code);
  1006. X        return((char *)0);
  1007. X    }
  1008. X    if(read(fd,font_ind,NASC + nspec) != NASC + nspec)
  1009. X    {
  1010. X        fprintf(stderr,"%s: read %d of %d of index table\n",i,NASC + nspec,Progname);
  1011. X        free(font_ind);
  1012. X        free(widths);
  1013. X        free(kerning);
  1014. X        free(code);
  1015. X        return((char *)0);
  1016. X    }
  1017. X    /* Now we can print the font description files; pr_font() also saves
  1018. X     * the font name for us, to return to main().
  1019. X     */
  1020. X    fname = pr_font(&font,widths,kerning,code,font_ind,funny_tab,funny_index,nspec);
  1021. X    free(font_ind);
  1022. X    free(widths);
  1023. X    free(kerning);
  1024. X    free(code);
  1025. X    return(fname);
  1026. X}
  1027. X
  1028. X
  1029. X/* Prints tha ascii font description.  Saves the fontname, properly
  1030. X * null-terminated, and returns it to rdfont() for pass back to main().
  1031. X */
  1032. Xchar *
  1033. Xpr_font(font,widths,kerning,code,font_ind,funny_tab,funny_index,nspec)
  1034. Xstruct Font *font;
  1035. Xchar *widths,*kerning,*code,*font_ind,*funny_tab;
  1036. Xshort *funny_index;
  1037. Xint nspec;
  1038. X{
  1039. X    int f,i,j,k,f_ind;
  1040. X    char *funny_str;
  1041. X    int nwidths;
  1042. X    FILE *fontf;
  1043. X    char fontname[16];
  1044. X    char intname[16];
  1045. X    char *fname;
  1046. X    int rti[4][256];        /* for a "reverse index table" into the font index */
  1047. X
  1048. X    nwidths = (int)(font->nwfont & BYTE);
  1049. X
  1050. X    /* make sure we have null-terminated names */
  1051. X    strncpy(fontname,font->namefont,10);
  1052. X    strncpy(intname,font->intname,10);
  1053. X    fontname[10] = '\0';
  1054. X    intname[10] = '\0';
  1055. X
  1056. X    /* now save a copy of the processed fontname for return (never freed) */
  1057. X    fname = savestr(fontname);
  1058. X
  1059. X    /* In case there's an original file, avoid overwriting it */
  1060. X    strcat(fontname,".new");
  1061. X
  1062. X    if((fontf = fopen(fontname,"w")) == (FILE *)0)
  1063. X    {
  1064. X        fprintf(stderr,"%s: can't open font file %s for writing\n",Progname,fontname);
  1065. X        exit(1);
  1066. X    }
  1067. X    if(debugging)        /* if compiled for debugging */
  1068. X        printf("\n\n\n\nwriting %s (%s)\n",fname,intname);
  1069. X
  1070. X    /* print the header information, from the font structure */
  1071. X    /* nwfont is printed as a comment, for reference          */
  1072. X    fprintf(fontf,"#nwfont %d\n",nwidths);
  1073. X    fprintf(fontf,"name %s\n",fname);
  1074. X    fprintf(fontf,"internalname %s\n",intname);
  1075. X    if(font->specfont)
  1076. X        fprintf(fontf,"special\n");
  1077. X    if(font->ligfont)
  1078. X        pr_lig(fontf,(char)(font->ligfont & BYTE));
  1079. X
  1080. X    /* widths[0] is spacewidth (if non-zero); real stuff starts at 1 */
  1081. X    if(widths[0] & BYTE)
  1082. X        fprintf(fontf,"spacewidth %u\n",(int)(widths[0] & BYTE));
  1083. X
  1084. X    widths[0] = '\0';
  1085. X    fprintf(fontf,"charset\n");
  1086. X    if(debugging)
  1087. X        printf("font index table\n\n");
  1088. X
  1089. X    /* Build a "reverse index table" which permits us to find the character
  1090. X     * which corresponds to a given width table entry.
  1091. X     */
  1092. X    bzero(rti,sizeof(rti));
  1093. X    for(j = 1; j < nspec + NASC ; ++j)
  1094. X    {
  1095. X        i = (int)(font_ind[j] & BYTE);
  1096. X        if(i > nwidths)
  1097. X        {
  1098. X            fprintf(stderr,"%s: width table too small ? (%d; need %d)\n",
  1099. X                    Progname,nwidths,i & BYTE);
  1100. X            continue;
  1101. X        }
  1102. X        /* If rti[i] is non-zero, we have two names for the same character,
  1103. X         * and it's a pain.  This is a hack, and only allows for four names.
  1104. X         * It would be unnecessary if "makefont" simply made a duplicate
  1105. X         * width table entry for each duplicate.  It also assumes that
  1106. X         * each of the indexes will be < 256.
  1107. X         * Tack the new value into the next free byte of the int.
  1108. X         */
  1109. X        if(i && rti[0][i])
  1110. X        {
  1111. X            for(k = 1; k < 4; ++k)
  1112. X            {
  1113. X                if(rti[k][i] == 0)
  1114. X                {
  1115. X                    rti[k][i] = j;
  1116. X                    break;
  1117. X                }
  1118. X            }
  1119. X            if(k == 4)
  1120. X            {
  1121. X                fprintf(stderr,"%s: too many duplicates, width index %d\n",Progname,i);
  1122. X                exit(1);
  1123. X            }
  1124. X        }
  1125. X        else
  1126. X            rti[0][i] = j;
  1127. X        if(debugging)
  1128. X        {
  1129. X            printf("%d\t%d\t",j,i);
  1130. X            if(j < NASC)
  1131. X                printf("\t\t\t%c\t%d  %d  %#o\n",j + 32,
  1132. X                    (int)(widths[i] & BYTE),(int)(kerning[i] & BYTE),(int)(code[i] & BYTE));
  1133. X            else
  1134. X            {
  1135. X                f_ind = (int)(funny_index[j - NASC] & SHORT);
  1136. X                funny_str = funny_tab + (f_ind & SHORT);
  1137. X                if(!funny_str)
  1138. X                    funny_str = "??";
  1139. X                printf("(f_ind=%d)\t%s\t%d\t%d\t%#o\n",f_ind,funny_str,
  1140. X                    (int)(widths[i] & BYTE),(int)(kerning[i] & BYTE),(int)(code[i] & BYTE));
  1141. X            }
  1142. X        }
  1143. X    }
  1144. X
  1145. X    /* Now print the width table, starting at 1 (since width 0 is spacewidth) */
  1146. X    if(debugging)
  1147. X    {
  1148. X        printf("\n\nWidth table\n\n");
  1149. X        printf("POS\tWIDTH\t\tKERN\t\tCODE\n");
  1150. X    }
  1151. X    for(i = 1; i < nwidths; ++i)
  1152. X    {
  1153. X        /* position in the font index table tells us what character 
  1154. X         * corresponds to this width table entry (if any).  Except we
  1155. X         * have to handle the hack for duplicate names...
  1156. X         */
  1157. X        for(k = 0; k < 4; ++k)
  1158. X        {
  1159. X            j = rti[k][i];
  1160. X            if(j == 0)
  1161. X            {
  1162. X                break;
  1163. X            }
  1164. X            f = (int)(font_ind[j] & BYTE);
  1165. X            if(f == 0)
  1166. X            {
  1167. X                continue;    /* not in this font */
  1168. X            }
  1169. X            if(f != i)
  1170. X            {
  1171. X                fprintf(stderr,"%s: reverse index table out of sync (%d != %d) at %d\n",Progname,f,i,j);
  1172. X                exit(1);
  1173. X            }
  1174. X            if(j < NASC)
  1175. X            {
  1176. X                if(debugging)
  1177. X                    printf("\t\t\t%c\t%d  %d  %#o\n",j + 32,
  1178. X                        (int)(widths[i] & BYTE),(int)(kerning[i] & BYTE),(int)(code[i] & BYTE));
  1179. X                if(k)
  1180. X                    fprintf(fontf,"%c\t\"\n",j + 32);    /* duplicate */
  1181. X                else
  1182. X                    fprintf(fontf,"%c\t%d\t%d\t%#o\n",j + 32,
  1183. X                        (int)(widths[i] & BYTE),(int)(kerning[i] & BYTE),(int)(code[i] & BYTE));
  1184. X            }
  1185. X            else
  1186. X            {
  1187. X                f_ind = (int)(funny_index[j - NASC] & SHORT);
  1188. X                funny_str = funny_tab + (f_ind & SHORT);
  1189. X                if(!funny_str)
  1190. X                    funny_str = "??";
  1191. X                if(debugging)
  1192. X                    printf("(f_ind=%d)\t%s\t%d\t%d\t%#o\n",f_ind,funny_str,
  1193. X                        (int)(widths[i] & BYTE),(int)(kerning[i] & BYTE),(int)(code[i] & BYTE));
  1194. X                if(k)
  1195. X                    fprintf(fontf,"%s\t\"\n",funny_str);
  1196. X                else
  1197. X                    fprintf(fontf,"%s\t%d  %d  %#o\n",funny_str,
  1198. X                        (int)(widths[i] & BYTE),(int)(kerning[i] & BYTE),(int)(code[i] & BYTE));
  1199. X            }
  1200. X        }
  1201. X    }
  1202. X    fclose(fontf);
  1203. X    printf("%s.out --> %s\n",fname,fontname);
  1204. X    return(fname);
  1205. X}
  1206. X
  1207. Xpr_lig(fontf,ligatures)
  1208. XFILE *fontf;
  1209. Xchar ligatures;
  1210. X{
  1211. X    fprintf(fontf,"ligatures ");
  1212. X    if(ligatures & LIG_FF)
  1213. X        fprintf(fontf," ff");
  1214. X    if(ligatures & LIG_FI)
  1215. X        fprintf(fontf," fi");
  1216. X    if(ligatures & LIG_FL)
  1217. X        fprintf(fontf," fl");
  1218. X    if(ligatures & LIG_FFI)
  1219. X        fprintf(fontf," ffi");
  1220. X    if(ligatures & LIG_FFL)
  1221. X        fprintf(fontf," ffl");
  1222. X    fprintf(fontf," 0\n");
  1223. X}
  1224. X
  1225. X/* 'nuff said...  */
  1226. Xunion kludge {
  1227. X    int i;
  1228. X    char c[4];
  1229. X} kludge;
  1230. X
  1231. X/* add byte y to x in the lowest zero-valued byte, if any. */
  1232. X
  1233. Xaddbyte(x,y)
  1234. Xint x,y;
  1235. X{
  1236. X    int i;
  1237. X
  1238. X    kludge.i = x;
  1239. X    for(i = 3; i >= 0; --i)
  1240. X        if((kludge.c[i] & BYTE) == 0)
  1241. X        {
  1242. X            kludge.c[i] = y & BYTE;
  1243. X            return(kludge.i);
  1244. X        }
  1245. X    return(x);
  1246. X}
  1247. X
  1248. X/* shift bytes down in an int, zeroing high byte */
  1249. X
  1250. Xshiftdown(x)
  1251. Xint x;
  1252. X{
  1253. X    int i;
  1254. X
  1255. X    kludge.i = x;
  1256. X    for(i = 3; i > 0; --i)
  1257. X        kludge.c[i] = kludge.c[i - 1];
  1258. X    kludge.c[0] = '\0';
  1259. X    return(kludge.i);
  1260. X}
  1261. /
  1262. echo 'x - readdesc.c'
  1263. sed 's/^X//' > readdesc.c << '/'
  1264. Xstatic char *RCSid = "$Header: readdesc.c,v 1.1 87/10/23 19:08:14 sysad Exp $";
  1265. X
  1266. X/*
  1267. X * $Log:    readdesc.c,v $
  1268. X * Revision 1.1  87/10/23  19:08:14  sysad
  1269. X * Initial revision
  1270. X * 
  1271. X * 
  1272. X */
  1273. X
  1274. X/* Read a binary "ditroff" font file and write an ascii equivalent.   */
  1275. X/* The written file is in a form which may be re-compiled.            */
  1276. X/*                                                                    */
  1277. X
  1278. X#include <stdio.h>
  1279. X#include <sys/file.h>
  1280. X#include "dev.h"
  1281. X
  1282. X#ifdef SYS5
  1283. X#define    rindex        strrchr
  1284. X#endif
  1285. X
  1286. X#define    SHORT    0xffff
  1287. X
  1288. Xchar *Progname;
  1289. Xstruct dev dev;
  1290. Xextern char *malloc(),*rdfont(),*rindex();
  1291. X
  1292. X/* debugging is always compiled off; use adb to set or unset it    */
  1293. Xint debugging = 0;        /* prints tables to stdout if set        */
  1294. X
  1295. Xmain(argc,argv)
  1296. Xint argc;
  1297. Xchar **argv;
  1298. X{
  1299. X    int fd,devsize,pointsizes,indexsize,funnysize,i;
  1300. X    short *points,*char_ind;
  1301. X    char *funny_chars,*ptr;
  1302. X    char **font_list,**fl;
  1303. X    char descbuf[256];
  1304. X    FILE *descfile;
  1305. X    char *descfn;
  1306. X
  1307. X    Progname = argv[0];
  1308. X    if(argc > 2)
  1309. X    {
  1310. X        fprintf(stderr,"usage: %s [descfile]\n",Progname);
  1311. X        exit(1);
  1312. X    }
  1313. X    else if(argc == 2)
  1314. X        descfn = argv[1];
  1315. X    else
  1316. X        descfn = "DESC.out";
  1317. X
  1318. X    if((fd = open(descfn,0,0)) < 0)
  1319. X    {
  1320. X        fprintf(stderr,"%s: can't open %s\n",Progname,descfn);
  1321. X        exit(2);
  1322. X    }
  1323. X    /* copy the name, strip the ".out", and replace it with ".new
  1324. X     * to get the name of the new ascii file.
  1325. X     */
  1326. X    sprintf(descbuf,"%s",descfn);
  1327. X    ptr = rindex(descbuf + 4,'.');
  1328. X    if(ptr)
  1329. X        *ptr = '\0';
  1330. X    strcat(descbuf,".new");
  1331. X    if((descfile = fopen(descbuf,"w")) == (FILE *)0)
  1332. X    {
  1333. X        fprintf(stderr,"%s: can't open new description file %s for writing\n",
  1334. X                Progname,descbuf);
  1335. X        exit(1);
  1336. X    }
  1337. X
  1338. X    /* Get the dev structure from the description file */
  1339. X    devsize = read(fd,(char *)&dev,sizeof(dev));
  1340. X    if(devsize != sizeof(dev))
  1341. X    {
  1342. X        fprintf(stderr,"%s: should have been %u bytes\n",Progname,sizeof(dev));
  1343. X        exit(3);
  1344. X    }
  1345. X
  1346. X    /* Allocate space for the sizes array, then read it in */
  1347. X    points = (short *)malloc((unsigned)(2 * (dev.nsizes + 1)));
  1348. X    pointsizes = read(fd,(char *)points,2 *(dev.nsizes + 1));
  1349. X    pointsizes /= 2;
  1350. X    if(--pointsizes != dev.nsizes)
  1351. X    {
  1352. X        fprintf(stderr,"%s: got %d of %d sizes\n",Progname,pointsizes,dev.nsizes);
  1353. X        exit(3);
  1354. X    }
  1355. X
  1356. X    /* Now the funny char index table */
  1357. X    char_ind = (short *)malloc((unsigned)(dev.nchtab * 2));
  1358. X    funny_chars = malloc(dev.lchname);
  1359. X    indexsize = read(fd,(char *)char_ind,dev.nchtab * 2);
  1360. X    indexsize /= 2;
  1361. X    if(indexsize != dev.nchtab)
  1362. X    {
  1363. X        fprintf(stderr,"%s: got %d of %d index entries\n",Progname,indexsize,dev.nchtab);
  1364. X        exit(4);
  1365. X    }
  1366. X
  1367. X    /* Now the funny char strings themseleves */
  1368. X    funnysize = read(fd,funny_chars,dev.lchname);
  1369. X    if(funnysize != dev.lchname)
  1370. X    {
  1371. X        fprintf(stderr,"%s: got %d of %d funny chars\n",Progname,funnysize,dev.lchname);
  1372. X        exit(5);
  1373. X    }
  1374. X    
  1375. X    /* allocate array space to hold pointers to the font names, which */
  1376. X    /* we accumulate as we read the font descriptions in rdfont().    */
  1377. X
  1378. X    font_list = (char **)malloc((unsigned)(dev.nfonts * sizeof(char *)));
  1379. X    fl = font_list;
  1380. X
  1381. X    /* Now read the font descriptions, print the tables and grab the  */
  1382. X    /* names String space for the names is allocated by rdfont(), so  */
  1383. X    /* we don't have to worry about saving them here.                 */
  1384. X
  1385. X    for(i = 0; i < dev.nfonts; ++i)
  1386. X        *fl++= rdfont(fd,indexsize,funny_chars,char_ind);
  1387. X    *fl = (char *)0;
  1388. X    if(debugging)
  1389. X        printf("\n\n\n\nwriting %s\n",descbuf);
  1390. X
  1391. X    /* Now that we've read everything, we can print the ascii description
  1392. X     * file; first the stuff from dev, then the funny char strings.
  1393. X     */
  1394. X    pr_dev(descfile,&dev,points,font_list);
  1395. X    pr_funny(descfile,funny_chars,char_ind,indexsize);
  1396. X    
  1397. X    fl = font_list;
  1398. X    if(debugging)
  1399. X    {
  1400. X        /* read the individual files, to see if they match */
  1401. X        for(i = 0; i < dev.nfonts; ++i)
  1402. X        {
  1403. X            if(fd >= 0)
  1404. X                close(fd);
  1405. X            if(!*fl)
  1406. X            {
  1407. X                fprintf(stderr,"%s: font #%d--no name\n",Progname,i);
  1408. X                ++fl;
  1409. X                continue;
  1410. X            }
  1411. X            sprintf(descbuf,"%s.out",*fl++);
  1412. X            fprintf(stderr,"checking %s\n",descbuf);
  1413. X            fd = open(descbuf,O_RDONLY,0);
  1414. X            if(fd < 0)
  1415. X                fprintf(stderr,"%s: can't open font file %s\n",Progname,*fl);
  1416. X            else
  1417. X                (void)rdfont(fd,indexsize,funny_chars,char_ind);
  1418. X        }
  1419. X    }
  1420. X    exit(0);
  1421. X}
  1422. X
  1423. X/* Print the "dev" structure to DESC.new, describing the general      */
  1424. X/* characteristics of the font style                                  */
  1425. X
  1426. Xpr_dev(descfile,dev,points,fontnames)
  1427. XFILE *descfile;
  1428. Xstruct dev *dev;
  1429. Xshort *points;
  1430. Xchar **fontnames;
  1431. X{
  1432. X    int npoints,i,j;
  1433. X
  1434. X    /* The first three are printed for reference only, as comments.
  1435. X     * They won't be used by mkfont.
  1436. X     */
  1437. X    fprintf(descfile,"#filesize %d\n",(int)(dev->filesize & SHORT));
  1438. X    fprintf(descfile,"#nchtab %d\n",(int)(dev->nchtab & SHORT));
  1439. X    fprintf(descfile,"#lchname %d\n",(int)(dev->lchname & SHORT));
  1440. X    fprintf(descfile,"fonts %d\t",(int)(dev->nfonts & SHORT));
  1441. X    pr_fonts(descfile,fontnames,(int)(dev->nfonts));
  1442. X    fprintf(descfile,"\nsizes\t");
  1443. X
  1444. X    npoints = (int)(dev->nsizes & SHORT);
  1445. X    for(i=0;i < npoints; )
  1446. X    {
  1447. X        for(j=0; (j < 15) && (i < npoints); ++j,++i)
  1448. X            fprintf(descfile,"%-4d",(int)(points[i] & SHORT));
  1449. X        fprintf(descfile,"\n\t\t");
  1450. X    }
  1451. X    fprintf(descfile," 0\n");
  1452. X    fprintf(descfile,"res %d\n",(int)(dev->res & SHORT));
  1453. X    fprintf(descfile,"hor %d\n",(int)(dev->hor & SHORT));
  1454. X    fprintf(descfile,"vert %d\n",(int)(dev->vert & SHORT));
  1455. X    fprintf(descfile,"unitwidth %d\n",(int)(dev->unitwidth & SHORT));
  1456. X    fprintf(descfile,"paperwidth %d\n",(int)(dev->paperwidth & SHORT));
  1457. X    fprintf(descfile,"paperlength %d\n",(int)(dev->paperlength & SHORT));
  1458. X    fprintf(descfile,"biggestfont %d\n",(int)(dev->biggestfont & SHORT));
  1459. X    fprintf(descfile,"sizescale %d\n",(int)(dev->sizescale & SHORT));
  1460. X}
  1461. X
  1462. X/* Print the character set to DESC.new                                */
  1463. X
  1464. Xpr_funny(descfile,str,ind,nstr)
  1465. XFILE *descfile;
  1466. Xchar *str;
  1467. Xshort *ind;
  1468. Xint nstr;
  1469. X{
  1470. X    int i,j,ent;
  1471. X    char *s;
  1472. X
  1473. X    fprintf(descfile,"charset\n");
  1474. X    if(debugging)
  1475. X        printf("\n\nFunny char table\n\nINDEX\tENT\tSTR\n");
  1476. X    for(i = 0; i < nstr; )
  1477. X    {
  1478. X        for(j = 0; (i < nstr) && (j < 15); ++i,++j)
  1479. X        {
  1480. X            ent = (int)(ind[i] & SHORT);
  1481. X            s = str+ent;
  1482. X            if(*s == '\0')
  1483. X                s = "??";
  1484. X            if(debugging)
  1485. X                printf("%d\t\t%d\t%s\n",i,ent,s);
  1486. X            /* The funny index table is null-terminated */
  1487. X            if((ent == 0) && (i != 0))
  1488. X            {
  1489. X                i = nstr;
  1490. X                break;
  1491. X            }
  1492. X            fprintf(descfile,"%4.4s",str+ent);
  1493. X        }
  1494. X        fprintf(descfile,"\n");
  1495. X    }
  1496. X}
  1497. X
  1498. X/* Print the names of the fonts to DESC.new.                          */
  1499. X
  1500. Xpr_fonts(descfile,names,nfonts)
  1501. XFILE *descfile;
  1502. Xchar **names;
  1503. Xint nfonts;
  1504. X{
  1505. X    int i;
  1506. X
  1507. X    /* assume they fit on one line */
  1508. X    if(!names)
  1509. X        return;
  1510. X    for(i = 0; i < nfonts; ++i)
  1511. X    {
  1512. X        if(names[i])
  1513. X            fprintf(descfile," %s",names[i]);
  1514. X        else
  1515. X            fprintf(descfile," ??");
  1516. X    }
  1517. X    fprintf(descfile,"\n");
  1518. X}
  1519. /
  1520. echo 'x - nextword.c'
  1521. sed 's/^X//' > nextword.c << '/'
  1522. Xstatic char *RCSid = "$Header: nextword.c,v 1.1 87/10/23 19:08:11 sysad Exp $";
  1523. X
  1524. X/*
  1525. X * $Log:    nextword.c,v $
  1526. X * Revision 1.1  87/10/23  19:08:11  sysad
  1527. X * Initial revision
  1528. X * 
  1529. X * 
  1530. X */
  1531. X
  1532. X#define    CNULL    (char *)0
  1533. X
  1534. X/*  nextword: return the next whitespace delimited word from the      */
  1535. X/*  string passed as argument.  The returned word is null- terminated */
  1536. X/*  and points to a static copy of the word.  Each time the routine   */
  1537. X/*  is called with a new string, the old string copy is freed, and a  */
  1538. X/*  static copy of the new string is made and the first word is       */
  1539. X/*  returned.  Subsequent calls with the same argument return         */
  1540. X/*  succeeding words, or null if no words remain.                     */
  1541. X/*                                                                    */
  1542. X
  1543. Xextern char *savestr();
  1544. X
  1545. X#include <ctype.h>
  1546. Xchar *
  1547. Xnextword(string)
  1548. Xchar *string;
  1549. X{
  1550. X    static char *ostring = CNULL;
  1551. X    static char *savedstr = CNULL;
  1552. X    static char *next = CNULL;
  1553. X    char *x,*start;
  1554. X
  1555. X    if((string == CNULL) || !*string)
  1556. X    {
  1557. X        /* no string or empty string */
  1558. X        if(savedstr)
  1559. X            free(savedstr);
  1560. X        savedstr = next = ostring = CNULL;
  1561. X        return(CNULL);
  1562. X    }
  1563. X
  1564. X    /* Have we seen this string before? */
  1565. X    if(string != ostring)
  1566. X    {
  1567. X        /* Nope; set up the copy and pointers */
  1568. X        ostring = string;
  1569. X        if(savedstr)
  1570. X            free(savedstr);
  1571. X        savedstr = savestr(string);
  1572. X        next = savedstr;
  1573. X    }
  1574. X    if(!next || !*next)
  1575. X        return(CNULL);
  1576. X
  1577. X    x = next;
  1578. X    /* strip off leading white space */
  1579. X    while(*x && (*x != '\n') && isspace(*x))
  1580. X        ++x;
  1581. X    start = x;                     /* x is the start of the word */
  1582. X    while(*x && (*x != '\n') && !isspace(*x))
  1583. X        ++x;
  1584. X    if(*x)
  1585. X    {
  1586. X        *x = '\0';                         /* null terminate the word */
  1587. X        next = ++x;
  1588. X    }
  1589. X    else next = CNULL;        /* end of string, no more words */
  1590. X    if(*start != '\n' && *start != '\0')
  1591. X    {
  1592. X        /* printf("nw = %s\n",start); /**/
  1593. X        return(start);
  1594. X    }
  1595. X    else
  1596. X        return(CNULL);
  1597. X}
  1598. /
  1599. echo 'x - strsave.c'
  1600. sed 's/^X//' > strsave.c << '/'
  1601. Xstatic char *RCSid = "$Header: strsave.c,v 1.1 87/10/23 19:08:15 sysad Exp $";
  1602. X
  1603. X/*
  1604. X * $Log:    strsave.c,v $
  1605. X * Revision 1.1  87/10/23  19:08:15  sysad
  1606. X * Initial revision
  1607. X * 
  1608. X * 
  1609. X */
  1610. X
  1611. X/*                                                                    */
  1612. X/* save a copy of the string 'string' some place.                     */
  1613. X/*                                                                    */
  1614. X
  1615. X#define    NULL    (char *)0
  1616. X#define NOWORD    "(null)"
  1617. Xchar *TOOMUCH = "savestr; too much space allocated\n";
  1618. X
  1619. Xchar *
  1620. Xsavestr(str)
  1621. Xchar *str;
  1622. X{
  1623. X    char *place,*save,*calloc();
  1624. X    char *tmp;
  1625. X    int i,j;
  1626. X
  1627. X    if( (i = strlen(str)) <= 0 )
  1628. X    {
  1629. X        save = "garbage";
  1630. X        i = 7;
  1631. X    }
  1632. X    else save = str;
  1633. X    if((place = calloc(1,i+1)) == NULL ) 
  1634. X    {
  1635. X        /* dont' want or need stdio */
  1636. X        write(2,TOOMUCH,sizeof(TOOMUCH));
  1637. X        exit(1);
  1638. X    }
  1639. X    tmp = place;
  1640. X    i++;    /* room for the null byte */
  1641. X    j = 0;
  1642. X    while ( (j++ < i) &&  *save )
  1643. X         *tmp++ = *save++;
  1644. X    *tmp = 0;
  1645. X    return(place);
  1646. X}
  1647. /
  1648. echo 'Part 01 of MKFONT/RDFONT complete.'
  1649. exit
  1650. _______
  1651.  
  1652. Duane
  1653.