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