This is mgribtoken.c in view mode; [Download] [Up]
/* * NOTES: * 1. mrti() assumes unsigned short is 2 bytes, MSB first * this may have to change for other architecture * 2. will it be possible to increase the encoded float array length * by "adding l" to create 256 aggregates of 3 or 4 floats each, as * opposed to 256 straight floats? (see appendix C, pg 163 of the * 'big' renderman manual) * 3. the name mrti should be changed to mgri (it sounds better) */ #include "mgribtoken.h" #include <stdio.h> #include "mg.h" #include "mgribP.h" #include "mgrib.h" #ifdef test #include <stdio.h> #endif #define BUFFERSIZE 1024*128 /* 128k buffer */ #define TMPSIZE 8192 #define SECTIONWIDTH 70 /* width of a section header */ #define STRINGDEF 0315 #define STRINGREF 0317 #define LNGSTRINGENCODE 0241 /* length follows, is unsigned short */ #define STRINGENCODE 0220 #define RIREQDEF 0314 #define RIREQREF 0246 #define FLOATARRAYDEF 0310 #define INTEGER 0201 /* unsigned short */ #define FLOAT 0244 void binary_token(int a1, va_list *alist); void ascii_token(int a1, va_list *alist); unsigned char *tokenbuffer=NULL; unsigned char *limit; unsigned char *ptr; /* following is the table: see mgribtoken.h (struct) for desc of fields */ static struct _table table[] = { {"", 0, 0, 0}, /* mr_NULL */ /* Ri Requests */ {"AttributeBegin", 14, 0, 0}, {"AttributeEnd", 12, 1, 0}, {"TransformBegin", 14, 2, 0}, {"TransformEnd", 12, 3, 0}, {"Identity", 8, 4, 0}, {"ConcatTransform", 15, 5, 0}, {"Surface", 7, 6, 0}, {"ShadingInterpolation", 20, 7, 0}, {"Color", 5, 8, 0}, {"Opacity", 7, 9, 0}, {"Polygon", 7, 10, 0}, {"PatchMesh", 9, 11, 0}, {"Format", 6, 12, 0}, {"Projection", 10, 13, 0}, {"Clipping", 8, 14, 0}, {"WorldBegin", 10, 15, 0}, {"WorldEnd", 8, 16, 0}, {"Display", 7, 17, 0}, {"ScreenWindow", 12, 19, 0}, {"LightSource", 11, 20, 0}, {"Sphere", 6, 21, 0}, {"Translate", 9, 22, 0}, {"Rotate", 6, 23, 0}, {"Cylinder", 8, 24, 0}, {"NuPatch", 7, 25, 0}, {"ShadingRate", 11, 26, 0}, {"Option", 6, 27, 0}, {"Illuminate", 10, 28, 0}, {"FrameBegin", 10, 29, 0}, {"FrameEnd", 8, 30, 0}, /* following are reserved - do not add */ /* or remove fields, just change them! */ {"", 0, 255, 0}, {"", 0, 255, 0}, {"", 0, 255, 0}, {"", 0, 255, 0}, {"", 0, 255, 0}, {"", 0, 255, 0}, {"", 0, 255, 0}, {"", 0, 255, 0}, {"", 0, 255, 0}, {"", 0, 255, 0}, {"", 0, 255, 0}, {"", 0, 255, 0}, {"", 0, 255, 0}, {"", 0, 255, 0}, {"", 0, 255, 0}, {"", 0, 255, 0}, {"", 0, 255, 0}, {"", 0, 255, 0}, {"", 0, 255, 0}, /* Strings - we start these out at position 50 */ {"P", 1, 0, 0}, {"N", 1, 1, 0}, {"Cs", 2, 2, 0}, {"Pw", 2, 3, 0}, {"Os", 2, 4, 0}, {"st", 2, 5, 0}, {"plastic", 7, 6, 0}, {"hplastic", 8, 7, 0}, {"eplastic", 8, 8, 0}, {"heplastic", 9, 9, 0}, {"constant", 8, 10, 0}, {"ambientlight", 12, 11, 0}, {"lightcolor", 10, 12, 0}, {"distantlight", 12, 13, 0}, {"intensity", 9, 14, 0}, {"file", 4, 15, 0}, {"rgb", 3, 16, 0}, {"rgba", 4, 17, 0}, {"Ka", 2, 18, 0}, {"Kd", 2, 19, 0}, {"Ks", 2, 20, 0}, {"specularcolor", 13, 21, 0}, {"roughness", 9, 22, 0}, {"fov", 3, 23, 0}, {"perspective", 11, 24, 0}, {"to", 2, 25, 0}, {"framebuffer", 11, 26, 0} }; /* initialize tokenbuffer */ void mrti_init() { if(tokenbuffer) free(tokenbuffer); tokenbuffer = (unsigned char *)malloc(BUFFERSIZE); tokenbuffer[0] = (char)0; limit = (unsigned char *)(tokenbuffer + BUFFERSIZE); ptr = tokenbuffer; } /* reset the ptr & tokenbuffer */ void mrti_reset() { ptr = tokenbuffer; tokenbuffer[0] = (char)0; } /* quick copy routine w/ ptr update */ void cat(unsigned char *s, char *a) { while(*(s++)=(*(a++))) ptr++; } /* routine will check buffer for possible overun, will realloc if needed */ /* generally, "worst case" values should be passed to check_buffer */ void check_buffer(int length) { if((unsigned char *)(ptr+length)>(unsigned char *)limit) { /* optinally check for maximum buffer allocation here */ long used = ptr - tokenbuffer; long avail = limit - tokenbuffer; /* Buffer grows exponentially, by factor of 1.5 each time */ do { avail += avail>>1; } while(used+length >= avail); tokenbuffer = (unsigned char *)realloc(tokenbuffer, avail); ptr = tokenbuffer + used; limit = tokenbuffer + avail; } } /* process variable size token list */ void mrti(int a1, ... ) { va_list alist; va_start(alist, a1); switch((int)(_mgribc->render_device & (RMD_BINARY|RMD_ASCII))) { case (int)RMD_BINARY: binary_token(a1, &alist); break; case (int)RMD_ASCII: ascii_token(a1, &alist); break; } va_end(alist); } /* return 1 when supplied token requires its own (ascii) line, 0 otherwise */ int line_initializer(int token) { /* THIS IS HACKISH - IT WILL CREATE A LINE FEED BEFORE */ /* IT CREATES THE NEW LINE, WHICH ISN'T ALWAYS GOOD!! */ if(token<STRINGBASE||token==mr_comment||token==mr_section|| (token>=mr_P && token<=mr_Os)) return 1; else return 0; } /* ASCII SUBPROCESSING */ void ascii_token(int token, va_list *alist) { int i; int count, number; int subsize; static int arraysize; static int expectSubArray=0; static char astring[128]; double nextfloat; /* va_arg converts floats to doubles */ float *floatptr; char *s; int len, add; do { if(expectSubArray && (token!=mr_subarray3)) { /* ERROR */ } /* check to see if we need to start a new line */ if(line_initializer(token) && *(ptr-1)!='\n') *(ptr++)='\n'; switch(token) { case mr_section: check_buffer(SECTIONWIDTH); /* should not exceed this */ s = va_arg(*alist, char*); len = strlen(s); if(len+3>SECTIONWIDTH) len = SECTIONWIDTH-3; /* 3 added characters */ *(ptr++)='\n'; cat(ptr,"# "); cat(ptr,s); cat(ptr," "); len = SECTIONWIDTH - 3 - len; while((len--)>0) *(ptr++)='*'; break; case mr_comment: s = va_arg(*alist, char*); len = strlen(s); check_buffer(len+2); cat(ptr,"# "); cat(ptr,s); break; case mr_header: s = va_arg(*alist, char*); len = strlen(s); check_buffer(len+2); cat(ptr,"##"); cat(ptr,s); break; case mr_nl: /* check for space */ check_buffer(2); if(*(ptr-1)==' ') ptr--; *(ptr++)='\n'; break; case mr_array: arraysize = va_arg(*alist, int); check_buffer(arraysize*16+4); /* how else can we do this? */ *(ptr++)='['; for(i=0;i<arraysize;i++) { nextfloat = va_arg(*alist, double); sprintf(astring,"%g ",nextfloat); cat(ptr, astring); } *(--ptr)=0; /* get rid of space */ cat(ptr,"] "); break; case mr_buildarray: arraysize = va_arg(*alist, int); check_buffer(1); expectSubArray = 1; *(ptr++)='['; break; case mr_parray: { int size; size = va_arg(*alist, int); check_buffer(2+16*size); *(ptr++)='['; /* if arraysize<0 then ERROR */ floatptr = va_arg(*alist, float*); for(i=0;i<size;i++) { sprintf(astring,"%g ",*(floatptr++)); cat(ptr,astring); } *(--ptr)=0; /* get rid of unwanted space */ cat(ptr,"] "); break; } case mr_subarray3: check_buffer(16*3+7); arraysize-=3; /* if arraysize<0 then ERROR */ floatptr = va_arg(*alist, float*); sprintf(astring,"%g %g %g ", *(floatptr),*(floatptr+1),*(floatptr+2)); cat(ptr,astring); if(arraysize<=0) { expectSubArray = 0; *(ptr-=3)=0; /* get rid of unwanted spaces */ cat(ptr,"] "); } break; case mr_int: number = va_arg(*alist, int); check_buffer(16); sprintf(astring,"%d ",number); cat(ptr,astring); break; case mr_float: nextfloat = va_arg(*alist, double); check_buffer(16); sprintf(astring,"%g ",nextfloat); cat(ptr,astring); break; case mr_intseq: /* OBSOLETE */ count = va_arg(*alist, int); check_buffer(count*16); for(i=0;i<count;i++) { number = va_arg(*alist, int); sprintf(astring,"%d ",number); cat(ptr,astring); } *(--ptr)=0; break; case mr_string: { char *string; string = va_arg(*alist, char *); len = strlen(string); check_buffer(len+3); *(ptr++)='"'; cat(ptr,string); *(ptr++)='"'; *(ptr++)=' '; break; } case mr_embed: { /* directly embed a string */ char *string; string = va_arg(*alist, char *); len = strlen(string); check_buffer(len); cat(ptr,string); break; } /* these requests require a trailing line feed */ case mr_attributebegin: case mr_attributeend: case mr_transformbegin: case mr_transformend: case mr_identity: case mr_polygon: case mr_worldbegin: case mr_worldend: case mr_frameend: check_buffer(table[token].len); cat(ptr,table[token].name); /* *(ptr++) = '\n'; */ break; /* these requests require a trailing space */ case mr_color: case mr_opacity: case mr_format: case mr_display: case mr_screenwindow: case mr_clipping: case mr_concattransform: case mr_projection: case mr_lightsource: case mr_illuminate: case mr_surface: case mr_sphere: case mr_patchmesh: case mr_rotate: case mr_translate: case mr_cylinder: case mr_nupatch: case mr_option: case mr_shadinginterpolation: case mr_shadingrate: case mr_framebegin: check_buffer(table[token].len+1); cat(ptr,table[token].name); *(ptr++)=' '; break; /* anything left over should be a string */ /* which requires quotes & trailing space */ /* (THIS SHOULD BE MOVED OUT OF SWITCH) */ default: check_buffer(table[token].len+3); *(ptr++)='"'; cat(ptr,table[token].name); *(ptr++)='"'; *(ptr++)=' '; break; } } while ((token=va_arg(*alist, int))!=mr_NULL); } /* BINARY SUBPROCESSING */ /* NOTE: some hardware will not support copying data types > 1 byte into an * arbitrary (unaligned) location. e.g. * *(unsigned short *)ptr = anUnsignedVariable * may be an illegal instruction. Therefore, macros which will copy these * values one byte at a time follow here and are used where needed. These * macros will work only with float sizes of 4 bytes (IEEE) & unsigned short * int sizes of 2 bytes */ #define COPYUSHORT( value ) *ptr++ = ((char *)&value)[0];\ *ptr++ = ((char *)&value)[1] #define COPYFLOAT( value ) *ptr++ = ((char *)&value)[0];\ *ptr++ = ((char *)&value)[1];\ *ptr++ = ((char *)&value)[2];\ *ptr++ = ((char *)&value)[3] void binary_token(int token, va_list *alist) { int i; static int expectSubArray=0; static int arraysize; float *floatptr; if(expectSubArray && (token!=mr_subarray3)) { /* ERROR */ } do { if(token>=STRINGBASE & token<mr_array) { /* The token is a string defintion/request */ if(!table[token].defined) { check_buffer(7 + table[token].len); *(ptr++)=STRINGDEF; *(ptr++)=table[token].reqn; if(table[token].len<16) { *(ptr++)=STRINGENCODE+table[token].len; } else { unsigned short length; length = (unsigned short) table[token].len; *(ptr++)=LNGSTRINGENCODE; COPYUSHORT(length); } cat(ptr,table[token].name); table[token].defined = 1; } *(ptr++)=STRINGREF; *(ptr++)=table[token].reqn; } else switch(token) { /* THESE SHOULD BE MOVE BEFORE SWITCH */ /* AND TURNED INTO A SPECIAL CASE */ case mr_attributebegin: case mr_attributeend: case mr_transformbegin: case mr_transformend: case mr_identity: case mr_polygon: case mr_worldbegin: case mr_worldend: case mr_color: case mr_format: case mr_display: case mr_screenwindow: case mr_clipping: case mr_concattransform: case mr_projection: case mr_lightsource: case mr_illuminate: case mr_surface: case mr_sphere: case mr_patchmesh: case mr_translate: case mr_rotate: case mr_cylinder: case mr_nupatch: case mr_option: case mr_shadinginterpolation: case mr_shadingrate: case mr_framebegin: case mr_frameend: check_buffer(7+table[token].len); if(!table[token].defined) { /* we must define it */ *(ptr++)=RIREQDEF; *(ptr++)=table[token].reqn; if(table[token].len<16) { *(ptr++)=STRINGENCODE+table[token].len; } else { unsigned short length; length = (unsigned short) table[token].len; *(ptr++)=LNGSTRINGENCODE; COPYUSHORT(length); } cat(ptr,table[token].name); table[token].defined = 1; } *(ptr++)=RIREQREF; *(ptr++)=table[token].reqn; break; case mr_array: { unsigned char arraycount; unsigned char *p; float f; arraycount = (unsigned char)va_arg(*alist, int); check_buffer(2+4*arraycount); *(ptr++)=FLOATARRAYDEF; *(ptr++)=arraycount; for(i=0;i<arraycount;i++) { /* will float be the same on each platform? (ieee?)*/ /* IS THIS NEXT STEP LEGAL?!? */ f = (float) va_arg(*alist, double); COPYFLOAT(f); } break; } case mr_buildarray: { unsigned char arraycount; arraysize = va_arg(*alist, int); arraycount = (unsigned char)arraysize; check_buffer(2); *(ptr++)=FLOATARRAYDEF; *(ptr++)=arraycount; expectSubArray = 1; break; } case mr_subarray3: { arraysize-=3; if(arraysize<0) /* ERROR */; check_buffer(12); /* 3*sizeof(float) */ floatptr = va_arg(*alist, float*); bcopy((char *)floatptr, (char *)ptr, 3*sizeof(float)); ptr+=3*sizeof(float); if(arraysize<=0) { expectSubArray = 0; } break; } case mr_parray: { unsigned char arraycount; arraycount = (unsigned char)va_arg(*alist, int); check_buffer(2+arraycount*4); *(ptr++)=FLOATARRAYDEF; *(ptr++)=arraycount; floatptr = va_arg(*alist, float*); bcopy((char *)floatptr, (char *)ptr, arraycount*sizeof(float)); ptr+=arraycount*sizeof(float); if(arraysize<=0) { expectSubArray = 0; } break; } case mr_int: { unsigned short number; check_buffer(3); number = (unsigned short)va_arg(*alist, int); *(ptr++) = INTEGER; COPYUSHORT(number); break; } case mr_float: { float afloat; check_buffer(5); afloat = (float)va_arg(*alist, double); *(ptr++) = FLOAT; COPYFLOAT(afloat); break; } case mr_intseq: { /* OBSOLETE */ unsigned short number; int count; count = va_arg(*alist, int); check_buffer(number*2); for(i=0;i<count;i++) { number = (unsigned short)va_arg(*alist, int); *(ptr++) = INTEGER; COPYUSHORT(number); } break; } case mr_string: { unsigned short length; char *string; string = va_arg(*alist, char *); length = (unsigned short) strlen(string); check_buffer(3+length); if(length<16) { *(ptr++)=STRINGENCODE+(char)length; } else { *(ptr++)=LNGSTRINGENCODE; COPYUSHORT(length); } cat(ptr,string); break; } case mr_embed: { /* no attempt is made to encode this becuase it's so general */ char *string; int length; string = va_arg(*alist, char *); length = strlen(string); check_buffer(length); cat(ptr,string); break; } case mr_nl: /* temporary for debugging (puts tokens on spereate lines) */ /* printf("\n"); */ break; } /* switch */ } while ((token=va_arg(*alist, int))!=mr_NULL); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.