1 #ifdef lint 2 static char sccsid[] = "@(#)makedev.c 1.1 (CWI) 1.1 85/03/27"; 3 #endif lint 4 /* 5 makedev: 6 read text info about a particular device 7 (e.g., cat, 202, aps5) from file, convert 8 it into internal (binary) form suitable for 9 fast reading by troff initialization (ptinit()). 10 11 Usage: 12 13 makedev DESC [ F ... ] 14 uses DESC to create a description file 15 using the information therein. 16 It creates the file DESC.out. 17 18 makedev F ... 19 makes the font tables for fonts F only, 20 creates files F.out. 21 22 DESC.out contains: 23 dev structure with fundamental sizes 24 list of sizes (nsizes+1) terminated by 0, as short's 25 indices of char names (nchtab * sizeof(short)) 26 char names as hy\0em\0... (lchname) 27 nfonts occurrences of 28 widths (nwidth) 29 kerning (nwidth) [ascender+descender only so far] 30 codes (nwidth) to drive actual typesetter 31 fitab (nchtab+128-32) 32 each of these is an array of char. 33 34 dev.filesize contains the number of bytes 35 in the file, excluding the dev part itself. 36 37 F.out contains the font header, width, kern, codes, and fitab. 38 Width, kern and codes are parallel arrays. 39 (Which suggests that they ought to be together?) 40 Later, we might allow for codes which are actually 41 sequences of formatting info so characters can be drawn. 42 */ 43 44 /* 45 * Changes made at the Mathematisch centrum: 46 * 47 * 1 added another table of shorts, with contains a number of the 48 * physical font where the char actual lives. This is done because 49 * the typesetter at the MC (harris 7400)has "mixed fonts". 50 * (for instance, the font with number 4478 contains the 51 * ligatures etc. for as well the times roman 52 * and the times italic fonts). 53 * This table (fcode(nwidth)) starts after the fitab, 54 * this is done so we don't have to change in troff t6.c setfp(). 55 * For the sake of compatibility, this change will only be effective 56 * if the field fonttab is set to 1. This change has to be wired 57 * in troff etc. as well. 58 * 59 * 2 The sans-serif fonts of the Harris doesn't have an italian 60 * equivalent, they are suppose to be made bij the Oblique 61 * facility of the Harris. This will slant the character by 62 * 9, 12 or 15 degrees. So another field in the font sruct is added 63 * for this function as well. 64 * 65 * 3 added some checking of input desciption (for instance declaring 66 * too many sizes). 67 * 68 * These changes are made by jaap akkerhuis, 1982 69 * 70 * Warning: using the spare fields may give bizarre effects, see comment 71 * at font.spare1 72 */ 73 74 #include "stdio.h" 75 #include "../dev.h" 76 77 #define BMASK 0377 78 #define skipline(f) while(getc(f) != '\n') 79 80 struct dev dev; 81 struct font font; 82 83 #define NSIZE 100 /* maximum number of sizes */ 84 short size[NSIZE]; 85 #define NCH 256 /* max number of characters with funny names */ 86 char chname[5*NCH]; /* character names, including \0 for each */ 87 short chtab[NCH]; /* index of character in chname */ 88 char nmseen[5*NCH]; /* The names we have seen */ 89 90 #define NFITAB (NCH + 128-32) /* includes ascii chars, but not non-graphics */ 91 char fitab[NFITAB]; /* font index table: position of char i on this font. */ 92 /* zero if not there */ 93 94 #define FSIZE 200 /* size of a physical font (e.g., 102 for cat) */ 95 char width[FSIZE]; /* width table for a physical font */ 96 char kern[FSIZE]; /* ascender+descender info */ 97 char code[FSIZE]; /* actual device codes for a physical font */ 98 short fcode[FSIZE]; /* MC:jna physical font number */ 99 100 #define NFONT 10 /* max number of default fonts */ 101 char fname[NFONT][10]; /* temp space to hold default font names */ 102 103 int fflag = 0; /* on if font table to be written */ 104 int fdout; /* output file descriptor */ 105 char *fout = "DESC.out"; 106 107 main(argc, argv) 108 char *argv[]; 109 { 110 FILE *fin; 111 char cmd[100], *p; 112 int i, totfont, v, check; 113 114 if ((fin = fopen("DESC", "r")) == NULL) { 115 fprintf(stderr, "makedev: can't open %s\n", argv[1]); 116 exit(1); 117 } 118 while (fscanf(fin, "%s", cmd) != EOF) { 119 if (cmd[0] == '#') /* comment */ 120 skipline(fin); 121 else if (strcmp(cmd, "res") == 0) { 122 fscanf(fin, "%hd", &dev.res); 123 } else if (strcmp(cmd, "hor") == 0) { 124 fscanf(fin, "%hd", &dev.hor); 125 } else if (strcmp(cmd, "vert") == 0) { 126 fscanf(fin, "%hd", &dev.vert); 127 } else if (strcmp(cmd, "unitwidth") == 0) { 128 fscanf(fin, "%hd", &dev.unitwidth); 129 } else if (strcmp(cmd, "sizescale") == 0) { 130 fscanf(fin, "%hd", &dev.sizescale); 131 } else if (strcmp(cmd, "paperwidth") == 0) { 132 fscanf(fin, "%hd", &dev.paperwidth); 133 } else if (strcmp(cmd, "paperlength") == 0) { 134 fscanf(fin, "%hd", &dev.paperlength); 135 } else if (strcmp(cmd, "spare1") == 0) { 136 fscanf(fin, "%hd", &dev.spare1); 137 } else if (strcmp(cmd, "spare2") == 0) { 138 fscanf(fin, "%hd", &dev.spare2); 139 } else if (strcmp(cmd, "sizes") == 0) { 140 dev.nsizes = 0; 141 while (fscanf(fin, "%d", &v) != EOF && v != 0) { 142 size[dev.nsizes++] = v; 143 if(dev.nsizes >= NSIZE) { /*MC:jna addition */ 144 fprintf(stderr, "Too many sizes\n"); 145 exit(3); 146 } 147 } 148 size[dev.nsizes] = 0; /* need an extra 0 at the end */ 149 } else if (strcmp(cmd, "fonts") == 0) { 150 fscanf(fin, "%hd", &dev.nfonts); 151 for (i = 0; i < dev.nfonts; i++) { 152 if ( i >= NFONT) { 153 fprintf(stderr,"Too many default fonts\n"); 154 exit(3); 155 } 156 fscanf(fin, "%s", fname[i]); 157 } 158 } else if (strcmp(cmd, "charset") == 0) { 159 p = chname; 160 dev.nchtab = 0; 161 while (fscanf(fin, "%s", p) != EOF) { 162 chtab[dev.nchtab++] = p - chname; 163 if (dev.nchtab > NCH) { 164 fprintf("Too many charnames at %s\n",p); 165 exit(3); 166 } 167 for (i = 0; i < dev.nchtab - 1; i++) 168 if (strcmp(&chname[chtab[i]], p) == 0) 169 printf("Warning: charname %s used more then once\n", p); 170 while (*p++) /* skip to end of name */ 171 ; 172 } 173 dev.lchname = p - chname; 174 chtab[dev.nchtab++] = 0; /* terminate properly */ 175 } else 176 fprintf(stderr, "makedev: unknown command %s\n", cmd); 177 } 178 if (argc > 0 && strcmp(argv[1], "DESC") == 0) { 179 check++; 180 fdout = creat(fout, 0666); 181 if (fdout < 0) { 182 fprintf(stderr, "makedev: can't open %s\n", fout); 183 exit(1); 184 } 185 write(fdout, &dev, sizeof(struct dev)); 186 write(fdout, size, (dev.nsizes+1) * sizeof(size[0])); /* we need a 0 on the end */ 187 write(fdout, chtab, dev.nchtab * sizeof(chtab[0])); 188 write(fdout, chname, dev.lchname); 189 totfont = 0; 190 for (i = 0; i < dev.nfonts; i++) { 191 totfont += dofont(fname[i]); 192 write(fdout, &font, sizeof(struct font)); 193 write(fdout, width, font.nwfont & BMASK); 194 write(fdout, kern, font.nwfont & BMASK); 195 write(fdout, code, font.nwfont & BMASK); 196 write(fdout, fitab, dev.nchtab+128-32); 197 if(font.fonttab == 1) 198 write(fdout, fcode, (font.nwfont & BMASK) * sizeof(fcode[0])); 199 } 200 lseek(fdout, 0L, 0); /* back to beginning to install proper size */ 201 dev.filesize = /* excluding dev struct itself */ 202 (dev.nsizes+1) * sizeof(size[0]) 203 + dev.nchtab * sizeof(chtab[0]) 204 + dev.lchname * sizeof(char) 205 + totfont * sizeof(char); 206 write(fdout, &dev, sizeof(struct dev)); 207 close(fdout); 208 argc--; 209 argv++; 210 } 211 for (i = 1; i < argc; i++) 212 dofont(argv[i]); 213 if( check) 214 checknames(); 215 exit(0); 216 } 217 218 dofont(name) /* create fitab and width tab for font */ 219 char *name; 220 { 221 FILE *fin; 222 int fdout; 223 int i, nw, spacewidth, n, v; 224 char buf[100], ch[10], s1[10], s2[10], s3[10],s4[10], cmd[30]; 225 char *p, *p1; 226 227 if ((fin = fopen(name, "r")) == NULL) { 228 fprintf(stderr, "makedev: can't open font %s\n", name); 229 exit(2); 230 } 231 sprintf(cmd, "%s.out", name); 232 fdout = creat(cmd, 0666); 233 for (i = 0; i < NFITAB; i++) 234 fitab[i] = 0; 235 for (i = 0; i < FSIZE; i++) { 236 width[i] = kern[i] = code[i] = 0; 237 fcode[i] = 0; 238 } 239 font.fonttab = font.slant = font.specfont = font.ligfont = spacewidth = 0; 240 font.spare1 = NULL; 241 font.namefont[0] = font.intname[0] = NULL; 242 243 while (fscanf(fin, "%s", cmd) != EOF) { 244 if (cmd[0] == '#') 245 skipline(fin); 246 else if (strcmp(cmd, "name") == 0) 247 fscanf(fin, "%s", font.namefont); 248 else if (strcmp(cmd, "internalname") == 0) 249 fscanf(fin, "%s", font.intname); 250 else if (strcmp(cmd, "special") == 0) 251 font.specfont = 1; 252 else if (strcmp(cmd, "fonttab") == 0) 253 font.fonttab = 1; 254 else if (strcmp(cmd, "slant") == 0) { 255 fscanf(fin, "%d", &i); 256 font.slant = i; 257 } else if (strcmp(cmd, "spare1") == 0) { 258 fscanf(fin, "%1s", s1); /*MC:jna %1s will get 1 char + 259 * a \0 added, so 260 * &font.spare1 will place 261 * a \0 in font.name[0] 262 */ 263 font.spare1 = s1[0]; 264 } else if (strcmp(cmd, "ligatures") == 0) { 265 font.ligfont = getlig(fin); 266 } else if (strcmp(cmd, "spacewidth") == 0) { 267 fscanf(fin, "%d", &spacewidth); 268 width[0] = spacewidth; /* width of space on this font */ 269 } else if (strcmp(cmd, "charset") == 0) { 270 skipline(fin); 271 nw = 0; 272 /* widths are origin 1 so fitab==0 can mean "not there" */ 273 /* 274 *MC:jna and so width[0] can mean spacewidth 275 * 276 * note that in charset part cann't be any comments! 277 */ 278 while (fgets(buf, 100, fin) != NULL) { 279 int x; 280 /* 281 printf(buf); 282 */ 283 if(font.fonttab == 1) { 284 x = sscanf(buf, "%s %s %s %s %s", ch,s1,s2,s3,s4); 285 if (x != 5 && s1[0] != '"') 286 printf("sscanf mismatch %d\n", x); 287 } 288 else { 289 x = sscanf(buf, "%s %s %s %s", ch, s1, s2, s3); 290 if (x != 4 && s1[0] != '"') 291 printf("sscanf mismatch %d\n", x); 292 } 293 if (s1[0] != '"') { /* it's a genuine new character */ 294 nw++; 295 if( nw > FSIZE) { 296 fprintf(stderr,"Too big font!\n"); 297 exit(1); 298 } 299 width[nw] = atoi(s1); 300 kern[nw] = atoi(s2); 301 /* temporarily, pick up one byte as code */ 302 if (s3[0] == '0') 303 sscanf(s3, "%o", &i); 304 else 305 sscanf(s3, "%d", &i); 306 code[nw] = i; 307 if(font.fonttab == 1) 308 fcode[nw] = atoi(s4); 309 } 310 /* otherwise it's a synonym for previous character, 311 /* so leave previous values intact 312 */ 313 if (strlen(ch) == 1) { /* it's ascii */ 314 if(fitab[ch[0] - 32]) 315 printf("Warning: redefining character %c\n", ch[0]); 316 fitab[ch[0] - 32] = nw; /* fitab origin omits non-graphics */ 317 } else { /* it has a funny name */ 318 for (i = 0; i < dev.nchtab; i++) 319 if (strcmp(&chname[chtab[i]], ch) == 0) { 320 if(fitab[i+128-32]) 321 printf("Warning: redefining character %s\n", ch); 322 fitab[i + 128-32] = nw; /* starts after the ascii */ 323 if(!nmseen[chtab[i]]) { 324 p = &nmseen[chtab[i]]; 325 p1 = ch; 326 while(*p1) 327 *p++ = *p1++; 328 } 329 break; 330 } 331 if (i >= dev.nchtab) 332 fprintf(stderr, "makedev: font %s: %s not in charset\n", name, ch); 333 } 334 } 335 nw++; 336 font.nwfont = n = nw; 337 } 338 } 339 if (spacewidth == 0) 340 width[0] = dev.res * dev.unitwidth / 72 / 3; 341 if (font.intname[0] == NULL) 342 fprintf(stderr, "Keyword internalname not specified\n"); 343 if (font.namefont[0] == NULL) 344 fprintf(stderr, "Keyword fontname not specified\n"); 345 fclose(fin); 346 347 write(fdout, &font, sizeof(struct font)); 348 write(fdout, width, font.nwfont & BMASK); 349 write(fdout, kern, font.nwfont & BMASK); 350 write(fdout, code, font.nwfont & BMASK); 351 write(fdout, fitab, dev.nchtab+128-32); 352 if(font.fonttab == 1) 353 write(fdout, fcode, (font.nwfont & BMASK) * sizeof(fcode[0])); 354 close(fdout); 355 v = sizeof(struct font) + 3 * n + dev.nchtab + 128-32; 356 if(font.fonttab == 1) 357 v += n * sizeof( short ); 358 fprintf(stderr, "%3s: %3d chars, width %3d, size %3d\n", 359 font.namefont, nw, width[0], v); 360 return v; 361 /* 362 * MC:jna v is the filesize of one font in bytes 363 */ 364 } 365 366 getlig(fin) /* pick up ligature list */ 367 FILE *fin; 368 { 369 int lig; 370 char temp[100]; 371 372 lig = 0; 373 while (fscanf(fin, "%s", temp) != EOF && strcmp(temp, "0") != 0) { 374 if (strcmp(temp, "fi") == 0) 375 lig |= LFI; 376 else if (strcmp(temp, "fl") == 0) 377 lig |= LFL; 378 else if (strcmp(temp, "ff") == 0) 379 lig |= LFF; 380 else if (strcmp(temp, "ffi") == 0) 381 lig |= LFFI; 382 else if (strcmp(temp, "ffl") == 0) 383 lig |= LFFL; 384 else 385 fprintf(stderr, "illegal ligature %s\n", temp); 386 } 387 skipline(fin); 388 return lig; 389 } 390 391 checknames() 392 { register int i, error; 393 394 error = 0; 395 396 for( i =0; i < dev.nchtab; i++) { 397 if( !nmseen[chtab[i]]) { 398 printf("Warning: %s not defined in any of the font(s)\n", 399 &chname[chtab[i]]); 400 if ( !error) 401 error++; 402 } 403 } 404 if (error) { 405 printf("This can lead to strange results when these "); 406 printf("characters are actually used!\n"); 407 } 408 printf("Number of special character names: %d\n", dev.nchtab -1); 409 } 410