1 /*
2 * gdsreader - simple Calma parser/printer tool
3 * Copyright (C) 1999 Serban-Mihai Popescu, serbanp@ix.netcom.com
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <math.h>
22 #include <string.h>
23 #include <strings.h>
24 #include <ctype.h>
25 #include <unistd.h>
26 #include <GDSstructs.h>
27 #include <GDSconsts.h>
28 #include <GDSglobals.h>
29 #include <GDStoPOV.h>
30 char *
MALLOC(int size)31 MALLOC(int size)
32 {
33 return (char *)malloc(size);
34 }
35
36 void
FREE(void * ptr)37 FREE(void *ptr)
38 {
39 free(ptr);
40 }
41
42 int
GDSreadInt2(unsigned char * record)43 GDSreadInt2(unsigned char* record)
44 {
45 int result;
46
47 result = record[0];
48 result <<= 8;
49 result += record[1];
50 if(result & 0x8000)
51 {
52 result &= 0x7fff;
53 result ^= 0x7fff;
54 result += 1;
55 result = -result;
56 }
57
58 return result;
59 }
60
61 int
GDSreadInt4(unsigned char * record)62 GDSreadInt4(unsigned char* record)
63 {
64 int i;
65 unsigned int result;
66
67 for(i = 0, result = 0; i < 4; i++)
68 {
69 result <<= 8;
70 result += record[i];
71 }
72 if(result & 0x80000000)
73 {
74 result &= 0x7fffffff;
75 result ^= 0x7fffffff;
76 result += 1;
77 result = -result;
78 }
79
80 return result;
81 }
82
83 double
GDSreadReal8(unsigned char * record)84 GDSreadReal8(unsigned char* record)
85 {
86 int i, sign, exponent;
87 unsigned long long mantissa_int;
88 double mantissa_float, result;
89
90 sign = record[0] & 0x80;
91 exponent = (record[0] & 0x7f) - 64;
92 mantissa_int = 0;
93
94 for(i = 1; i < 8; i++)
95 {
96 mantissa_int <<= 8;
97 mantissa_int += record[i];
98 }
99 mantissa_float = (double)mantissa_int / pow(2, 56);
100 result = mantissa_float * pow(16, (float)exponent);
101 if(sign)
102 result = -result;
103
104 return result;
105 }
106
107 char *
GDSreadString(unsigned char * record,int len)108 GDSreadString(unsigned char* record, int len)
109 {
110 char *result, string[1024];
111 int i;
112
113 if(len > 1024)
114 len = 1024;
115 for(i = 0; i < len; i++)
116 {
117 string[i] = record[i];
118 if(record[i] == '\0')
119 break;
120 }
121 string[len] = '\0';
122
123 result = strdup(string);
124 return result;
125 }
126
127
128
129 const char *POVKeyWords[]={
130 "aa_level", "aa_threshold", "abs", "absorption", "accuracy", "acos",
131 "acosh", "adaptive", "adc_bailout", "agate", "agate_turb", "all",
132 "all_intersections", "alpha", "altitude", "always_sample", "ambient",
133 "ambient_light", "angle", "aperture", "append", "arc_angle", "area_light",
134 "array", "asc", "ascii", "asin", "asinh", "assumed_gamma", "atan",
135 "atan2", "atanh", "autostop", "average", "b_spline", "background",
136 "bezier_spline", "bicubic_patch", "black_hole", "blob", "blue",
137 "blur_samples", "bounded_by", "box", "boxed", "bozo", "break", "brick",
138 "brick_size", "brightness", "brilliance", "bump_map", "bump_size",
139 "bumps", "camera", "case", "caustics", "ceil", "cells", "charset",
140 "checker", "chr", "circular", "clipped_by", "clock", "clock_delta",
141 "clock_on", "collect", "color", "color_map", "colour", "colour_map",
142 "component", "composite", "concat", "cone", "confidence", "conic_sweep",
143 "conserve_energy", "contained_by", "control0", "control1", "coords",
144 "cos", "cosh", "count", "crackle", "crand", "cube", "cubic",
145 "cubic_spline", "cubic_wave", "cutaway_textures", "cylinder",
146 "cylindrical", "debug", "declare", "default", "defined", "degrees",
147 "density", "density_file", "density_map", "dents", "df3", "difference",
148 "diffuse", "dimension_size", "dimensions", "direction", "disc",
149 "dispersion", "dispersion_samples", "dist_exp", "distance", "div",
150 "double_illuminate", "eccentricity", "else", "emission", "end", "error",
151 "error_bound", "evaluate", "exp", "expand_thresholds", "exponent",
152 "exterior", "extinction", "face_indices", "facets", "fade_color",
153 "fade_colour", "fade_distance", "fade_power", "falloff", "falloff_angle",
154 "false", "fclose", "file_exists", "filter", "final_clock", "final_frame",
155 "finish", "fisheye", "flatness", "flip", "floor", "focal_point", "fog",
156 "fog_alt", "fog_offset", "fog_type", "fopen", "form", "frame_number",
157 "frequency", "fresnel", "function", "gather", "gif", "global_lights",
158 "global_settings", "gradient", "granite", "gray", "gray_threshold",
159 "green", "height_field", "hexagon", "hf_gray_16", "hierarchy",
160 "hypercomplex", "hollow", "if", "ifdef", "iff", "ifndef", "image_height",
161 "image_map", "image_pattern", "image_width", "include", "initial_clock",
162 "initial_frame", "inside", "inside_vector", "int", "interior",
163 "interior_texture", "internal", "interpolate", "intersection",
164 "intervals", "inverse", "ior", "irid", "irid_wavelength", "isosurface",
165 "jitter", "jpeg", "julia", "julia_fractal", "lambda", "lathe", "leopard",
166 "light_group", "light_source", "linear_spline", "linear_sweep", "ln",
167 "load_file", "local", "location", "log", "look_at", "looks_like",
168 "low_error_factor", "macro", "magnet", "major_radius", "mandel",
169 "map_type", "marble", "material", "material_map", "matrix", "max",
170 "max_extent", "max_gradient", "max_intersections", "max_iteration",
171 "max_sample", "max_trace", "max_trace_level", "media",
172 "media_attenuation", "media_interaction", "merge", "mesh", "mesh2",
173 "metallic", "method", "metric", "min", "min_extent", "minimum_reuse",
174 "mod", "mortar", "natural_spline", "nearest_count", "no", "no_bump_scale",
175 "no_image", "no_reflection", "no_shadow", "noise_generator", "normal",
176 "normal_indices", "normal_map", "normal_vectors", "number_of_waves",
177 "object", "octaves", "off", "offset", "omega", "omnimax", "on", "once",
178 "onion", "open", "orient", "orientation", "orthographic", "panoramic",
179 "parallel", "parametric", "pass_through", "pattern", "perspective", "pgm",
180 "phase", "phong", "phong_size", "photons", "pi", "pigment", "pigment_map",
181 "pigment_pattern", "planar", "plane", "png", "point_at", "poly",
182 "poly_wave", "polygon", "pot", "pow", "ppm", "precision", "precompute",
183 "pretrace_end", "pretrace_start", "prism", "prod", "projected_through",
184 "pwr", "quadratic_spline", "quadric", "quartic", "quaternion",
185 "quick_color", "quick_colour", "quilted", "radial", "radians",
186 "radiosity", "radius", "rainbow", "ramp_wave", "rand", "range", "ratio",
187 "read", "reciprocal", "recursion_limit", "red", "reflection",
188 "reflection_exponent", "refraction", "render", "repeat", "rgb", "rgbf",
189 "rgbft", "rgbt", "right", "ripples", "rotate", "roughness", "samples",
190 "save_file", "scale", "scallop_wave", "scattering", "seed", "select",
191 "shadowless", "sin", "sine_wave", "sinh", "size", "sky", "sky_sphere",
192 "slice", "slope", "slope_map", "smooth", "smooth_triangle", "solid",
193 "sor", "spacing", "specular", "sphere", "sphere_sweep", "spherical",
194 "spiral1", "spiral2", "spline", "split_union", "spotlight", "spotted",
195 "sqr", "sqrt", "statistics", "str", "strcmp", "strength", "strlen",
196 "strlwr", "strupr", "sturm", "substr", "sum", "superellipsoid", "switch",
197 "sys", "t", "tan", "tanh", "target", "text", "texture", "texture_list",
198 "texture_map", "tga", "thickness", "threshold", "tiff", "tightness",
199 "tile2", "tiles", "tolerance", "toroidal", "torus", "trace", "transform",
200 "translate", "transmit", "triangle", "triangle_wave", "true", "ttf",
201 "turb_depth", "turbulence", "type", "u", "u_steps", "ultra_wide_angle",
202 "undef", "union", "up", "use_alpha", "use_color", "use_colour",
203 "use_index", "utf8", "uv_indices", "uv_mapping", "uv_vectors", "v",
204 "v_steps", "val", "variance", "vaxis_rotate", "vcross", "vdot", "version",
205 "vertex_vectors", "vlength", "vnormalize", "vrotate", "vstr",
206 "vturbulence", "warning", "warp", "water_level", "waves", "while",
207 "width", "wood", "wrinkles", "write", "x", "y", "yes", "z",
208 NULL
209 };
210
211
212
213
214
215 /* Returns hashed string. Uses hex val of chars from right to left */
216 char *
GetPOVhashedStr(char * s)217 GetPOVhashedStr(char *s)
218 {
219 int i,l;
220 char *retv,cb[2]=" ";
221 char c;
222 l=strlen(s);
223 retv=(char *)MALLOC(sizeof(char)*41);
224 retv[0]='X';
225 retv[1]='\0';
226 i=l;
227 while (i>=0 && strlen(retv)<=38) {
228 c=(s[i]&0xf0)>>4;
229 if (c>9) cb[0]='A'+c-9; else cb[0]='0'+c;
230 strcat(retv,cb);
231 c=s[i]&0x0f;
232 if (c>9) cb[0]='A'+c-9; else cb[0]='0'+c;
233 strcat(retv,cb);
234 i--;
235 }
236 return(retv);
237 }
238
239
240 /*
241 Escapes a string used in GDS format so it cannot conflict with
242 POVRAY. Returns a dynamically allocated string which should be
243 freed using FREE.
244
245 POVRAY identifiers are [A-Za-z0-9_] up to 40 characters long, and
246 the first character must be alphabetic.
247
248 All POVRAY reserved words are lower case. If there is a upper case
249 char anywhere, there is no conflict.
250
251 Any word which is either too long, or would become too due to
252 escaping, will be hashed to a pseudo-random identifier.
253
254 I use layer texture identifiers with GDS_TEX_%d, so if that matches,
255 we need to fix too.
256
257 */
258
259 char *
GDSEscPovString(char * s)260 GDSEscPovString(char *s)
261 {
262 int i,l;
263 char *retv=NULL;
264 if (s==NULL) return(s);
265 if ((l=strlen(s))>40) return(GetPOVhashedStr(s));
266 if (!strncmp(s,"GDS_TEX_",8)) { /* close enough to a
267 layer ID to require an escape. */
268 return(GetPOVhashedStr(s));
269 }
270 retv=(char *)MALLOC(sizeof(char)*41);
271 strcpy(retv,s);
272 if (l==0) return(retv);
273 /* Keyword Test */
274 i=0;
275 while (POVKeyWords[i]!=NULL) {
276 if (!strcmp(retv,POVKeyWords[i])) {
277 /* We have a keyword and must escape. Can add a 'K' at the
278 end to escape .*/
279 strcat(retv,"K");
280 return(retv);
281 }
282 i++;
283 }
284 i=0;
285 while (i<l) {
286 /* Fix ith character */
287 if (!isalpha(retv[i]) && !(i>0 && (isdigit(retv[i]) || retv[i]=='_'))) {
288 /* Must escape bad character. Can use E_ for now. Later might
289 use E__HEXVAL_ to make more reversable. */
290 if (l+1<=40) { /* We can still fit it. */
291 memmove(i+retv+1,i+retv,l-i+1);
292 retv[i]='E';
293 retv[i+1]='_';
294 l++;
295 } else { /* Give up */
296 FREE(retv);
297 return(GetPOVhashedStr(s));
298 }
299 }
300 i++;
301 }
302 return(retv);
303 }
304
305
306
307
308
309
310
311 void
GDSaddDates(GDSlibrary * libptr,unsigned char * record)312 GDSaddDates(GDSlibrary* libptr, unsigned char* record)
313 {
314 int my, mmo, md, mh, mmi, ms;
315 int ay, amo, ad, ah, ami, as;
316 char string[1024];
317
318 my = GDSreadInt2(record + 2);
319 mmo = GDSreadInt2(record + 4);
320 md = GDSreadInt2(record + 6);
321 mh = GDSreadInt2(record + 8);
322 mmi = GDSreadInt2(record + 10);
323 ms = GDSreadInt2(record + 12);
324
325 ay = GDSreadInt2(record + 14);
326 amo = GDSreadInt2(record + 16);
327 ad = GDSreadInt2(record + 18);
328 ah = GDSreadInt2(record + 20);
329 ami = GDSreadInt2(record + 22);
330 as = GDSreadInt2(record + 24);
331 sprintf(string, "%d/%d/%d at %d:%d:%d", mmo, md, my, mh, mmi, ms);
332 libptr->lastmod = strdup(string);
333 sprintf(string, "%d/%d/%d at %d:%d:%d", amo, ad, ay, ah, ami, as);
334 libptr->lastacc = strdup(string);
335 }
336
337 int
GDSrecordType(unsigned char record_type)338 GDSrecordType(unsigned char record_type)
339 {
340 int rtype;
341
342 switch(record_type)
343 {
344 case 0x00:
345 rtype = HEADER;
346 break;
347 case 0x01:
348 rtype = BGNLIB;
349 break;
350 case 0x02:
351 rtype = LIBNAME;
352 break;
353 case 0x03:
354 rtype = UNITS;
355 break;
356 case 0x04:
357 rtype = ENDLIB;
358 break;
359 case 0x05:
360 rtype = BGNSTR;
361 break;
362 case 0x06:
363 rtype = STRNAME;
364 break;
365 case 0x07:
366 rtype = ENDSTR;
367 break;
368 case 0x08:
369 rtype = BOUNDARY;
370 break;
371 case 0x09:
372 rtype = PATH;
373 break;
374 case 0x0a:
375 rtype = SREF;
376 break;
377 case 0x0b:
378 rtype = AREF;
379 break;
380 case 0x0c:
381 rtype = TEXT;
382 break;
383 case 0x0d:
384 rtype = LAYER;
385 break;
386 case 0x0e:
387 rtype = DATATYPE;
388 break;
389 case 0x0f:
390 rtype = WIDTH;
391 break;
392 case 0x10:
393 rtype = XY;
394 break;
395 case 0x11:
396 rtype = ENDEL;
397 break;
398 case 0x12:
399 rtype = SNAME;
400 break;
401 case 0x13:
402 rtype = COLROW;
403 break;
404 case 0x14:
405 rtype = TEXTNODE;
406 break;
407 case 0x15:
408 rtype = NODE;
409 break;
410 case 0x16:
411 rtype = TEXTTYPE;
412 break;
413 case 0x17:
414 rtype = PRESENTATION;
415 break;
416 case 0x18:
417 rtype = SPACING;
418 break;
419 case 0x19:
420 rtype = STRING;
421 break;
422 case 0x1a:
423 rtype = STRANS;
424 break;
425 case 0x1b:
426 rtype = MAG;
427 break;
428 case 0x1c:
429 rtype = ANGLE;
430 break;
431 case 0x1d:
432 rtype = UINTEGER;
433 break;
434 case 0x1e:
435 rtype = USTRING;
436 break;
437 case 0x1f:
438 rtype = REFLIBS;
439 break;
440 case 0x20:
441 rtype = FONTS;
442 break;
443 case 0x21:
444 rtype = PATHTYPE;
445 break;
446 case 0x22:
447 rtype = GENERATIONS;
448 break;
449 case 0x23:
450 rtype = ATTRTABLE;
451 break;
452 case 0x24:
453 rtype = STYPTABLE;
454 break;
455 case 0x25:
456 rtype = STRTYPE;
457 break;
458 case 0x26:
459 rtype = ELFLAGS;
460 break;
461 case 0x27:
462 rtype = ELKEY;
463 break;
464 case 0x28:
465 rtype = LINKTYPE;
466 break;
467 case 0x29:
468 rtype = LINKKEYS;
469 break;
470 case 0x2a:
471 rtype = NODETYPE;
472 break;
473 case 0x2b:
474 rtype = PROPATTR;
475 break;
476 case 0x2c:
477 rtype = PROPVALUE;
478 break;
479 case 0x2d:
480 rtype = BOX;
481 break;
482 case 0x2e:
483 rtype = BOXTYPE;
484 break;
485 case 0x2f:
486 rtype = PLEX;
487 break;
488 case 0x30:
489 rtype = BGNEXTN;
490 break;
491 case 0x31:
492 rtype = ENDTEXTN;
493 break;
494 case 0x32:
495 rtype = TAPENUM;
496 break;
497 case 0x33:
498 rtype = TAPECODE;
499 break;
500 case 0x34:
501 rtype = STRCLASS;
502 break;
503 case 0x35:
504 rtype = RESERVED;
505 break;
506 case 0x36:
507 rtype = FORMAT;
508 break;
509 case 0x37:
510 rtype = MASK;
511 break;
512 case 0x38:
513 rtype = ENDMASKS;
514 break;
515 case 0x39:
516 rtype = LIBDIRSIZE;
517 break;
518 case 0x3a:
519 rtype = SRFNAME;
520 break;
521 case 0x3b:
522 rtype = LIBSECUR;
523 break;
524 default:
525 rtype = UNKNOWN;
526 break;
527 }
528 return rtype;
529 }
530
531 void
GDSunreadRecord(int gdsfildes,int nbytes)532 GDSunreadRecord(int gdsfildes, int nbytes)
533 {
534 lseek(gdsfildes, -nbytes, SEEK_CUR);
535 return;
536 }
537
538 int
GDSreadRecord(int gdsfildes,unsigned char ** record,int * nbytes)539 GDSreadRecord(int gdsfildes, unsigned char **record, int *nbytes)
540 {
541 int nread;
542 unsigned char nbyte_array[2];
543
544 if((nread = read(gdsfildes, nbyte_array, 2)) != 2)
545 {
546 if(nread == 1)
547 {
548 fprintf(stderr, "Error in reading the GDS file. Aborting\n");
549 exit(1);
550 }
551 else
552 {
553 *record = NULL;
554 return -1;
555 }
556 }
557 *nbytes = nbyte_array[0] * 256 + nbyte_array[1];
558 if(*nbytes != 0)
559 {
560 *record = (unsigned char *)MALLOC(*nbytes - 2);
561 if((nread = read(gdsfildes, *record, *nbytes - 2)) != *nbytes - 2)
562 {
563 fprintf(stderr, "Error in reading the GDS file. Aborting\n");
564 exit(1);
565 }
566 }
567 return GDSrecordType((*record)[0]);
568 }
569
570
571 /* Returns dynamically allocated string. */
GDSpsStyleNoToTEXName(int i)572 char *GDSpsStyleNoToTEXName(int i)
573 {
574
575 const char fstr1[]="GDS_TEX_%d";
576 const char fstr2[]="GDS_TEX_%d_%d";
577 char *retstr;
578 if (psStyles[i].dataspec) {
579 retstr=(char *)MALLOC(sizeof(char)*(strlen(fstr2)+30));
580 sprintf(retstr,fstr2,psStyles[i].gdsno,psStyles[i].datatype);
581
582 } else {
583 retstr=(char *)MALLOC(sizeof(char)*(strlen(fstr2)+15));
584 sprintf(retstr,fstr1,psStyles[i].gdsno);
585 }
586 return(retstr);
587 }
588
589
590
GDSLayerToTEXName(layer * layerptr)591 char *GDSLayerToTEXName(layer *layerptr)
592 {
593 int i;
594 i=layer_to_style_no(layerptr);
595 return(GDSpsStyleNoToTEXName(i));
596 }
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611