/* ecdset.c Copyright (c) Kapteyn Laboratorium Groningen 1994 All Rights Reserved. #> ecdset.dc2 Function: ECDSET Purpose: Encodes set and subsets into a string. The set MUST exist! Category: USER IO File: ecdset.c Author: K.G. Begeman Use: INTEGER ECDSET( STRING, Output CHARACTER*(*) SET, Input CHARACTER*(*) SUBSETS, Input INTEGER ARRAY NSUBS ) Input INTEGER ECDSET Returns 0 on success, else: -1: Set does not exist. -2: Cannot allocate sufficient memory. -3: Encoded string longer than output buffer. -4: Impossible to encode. STRING Output encoded string. SET Name of set. SUBSETS The subset coordinate words. NSUBS The number of subsets. Related Docs: dcdset.dc2 Updates: Jan 13, 1994: KGB, Document created. #< Fortran to C interface: @ integer function ecdset( character, character, integer, integer ) */ #include "ctype.h" /* */ #include "stdio.h" /* */ #include "stdlib.h" /* */ #include "string.h" /* */ #include "gipsyc.h" /* GIPSY definitions */ #include "gds_close.h" /* gds_close_c */ #include "gds_exist.h" /* gds_exist_c */ #include "gdsc_grid.h" /* gdsc_grid_c */ #include "gdsc_name.h" /* gdsc_name_c */ #include "gdsc_ndims.h" /* gdsc_ndims_c */ #include "nelc.h" /* nelc_c */ #define MAXSTRINGLEN 1024 /* max. length of strings */ #define MAXCTYPELEN 70 /* max. length of axis name */ #define RETURN( r ) \ { \ if ( ax != NULL ) { \ int m; \ for ( m = 0; m < ndef; m++ ) { \ if ( ax[m].grid != NULL ) free( ax[m].grid ); \ if ( ax[m].step != NULL ) free( ax[m].step ); \ } \ free( ax ); \ } \ return( r ); \ } #define SHIP( out ) \ { \ int n = 0; \ while ( out[n] && nc < string.l ) { \ string.a[nc++] = out[n++]; \ } \ if ( out[n] ) RETURN( -3 ); \ } typedef struct { char ctype[MAXCTYPELEN]; /* axis name */ fint axnum; /* axis sequence number */ fint *grid; /* the grids on axis */ fint *step; /* the grid step */ fint *user; /* user entered */ fint ngrid; /* positions on axis */ fint nstep; /* number of steps */ fint nsequ; /* sequences */ } ax_struct; /* * compar is called by qsort to sort the axis in the order as probably * defined in the command. */ static int compar( const void *a1, const void *a2 ) { const ax_struct *b1 = a1; const ax_struct *b2 = a2; return( b2->nsequ - b1->nsequ ); } /* * ecdset encodes a set name and subsets into text (i.e. as would have been * entered by the user). The status indicates whether an error occurred: * value of status meaning * 0 No error. * -1 Set does not exist. * -2 Cannot allocate sufficient memory. * -3 Encoded string longer than output buffer. * -4 Impossible to encode. */ fint ecdset_c( fchar string, fchar set, fint subsets[], fint *nsubs ) { ax_struct *ax = NULL; /* the ax struct */ fint count; /* counter */ fint gerror = 0; /* gds error return */ fint nc = 0; /* number of characters shipped */ fint m, n; /* loop counters */ fint naxis; /* number of axes */ fint ndef = 0; /* number of defined axes */ fint subset; /* subset number */ fint toplevel = 0; /* whole set */ for ( n = 0; n < string.l; string.a[n++] = ' ' ); if ( !tobool( gds_exist_c( set, &gerror ) ) || gerror ) { return( -1 ); } naxis = gdsc_ndims_c( set, &toplevel ); /* dimension of set */ subset = subsets[0]; /* first subset */ for ( n = 0; n < naxis; n++ ) { /* loop to get defined axes */ fint axnum; /* the axis number */ fint grid; /* grid number */ axnum = n + 1; /* current axis number */ gerror = 0; /* reset */ grid = gdsc_grid_c( set, &axnum, &subset, &gerror ); if ( gerror == 0 ) { /* axis defined */ fchar ctype; /* points to buffer for axis name */ ax = realloc( ax, sizeof( ax_struct ) * ( ndef + 1 ) ); if ( ax == NULL ) RETURN( -2 ); /* error */ ax[ndef].axnum = axnum; /* axis sequence number */ ax[ndef].nstep = 0; ax[ndef].ngrid = 0; ax[ndef].grid = NULL; ax[ndef].step = NULL; ax[ndef].user = NULL; ctype.a = ax[ndef].ctype; ctype.l = MAXCTYPELEN; gdsc_name_c( ctype, set, &axnum, &gerror ); ctype.a[nelc_c( ctype )] = 0; ndef++; } } gerror = 0; nc = nelc_c( set ); if ( nc > string.l ) RETURN( -3 ); strncpy( string.a, set.a, nc ); if ( ndef == 0 ) { if ( (*nsubs) != 1 ) RETURN( -4 ); RETURN( 0 ); } for ( m = 0; m < ndef; m++ ) { ax[m].grid = calloc( (*nsubs), sizeof( fint ) ); if ( ax[m].grid == NULL ) RETURN( -2 ); ax[m].step = calloc( (*nsubs), sizeof( fint ) ); if ( ax[m].step == NULL ) RETURN( -2 ); ax[m].user = calloc( (*nsubs), sizeof( fint ) ); if ( ax[m].user == NULL ) RETURN( -2 ); } for ( n = 0; n < (*nsubs); n++ ) { for ( m = 0; m < ndef; m++ ) { ax[m].grid[n] = gdsc_grid_c( set, &ax[m].axnum, &subsets[n], &gerror ); } } for ( m = 0; m < ndef; m++ ) { fint okay; fint n1, n2; fint ns = 1; fint nt = (*nsubs); ax[m].nsequ = ns; while ( ns < (*nsubs) ) { ns++; if ( ( (*nsubs) % ns ) == 0 ) { nt = (*nsubs) / ns; for ( okay = 1, n1 = 0; n1 < nt && okay; n1++ ) { for ( n2 = 1; n2 < ns && okay; n2++ ) { okay = ( ax[m].grid[n1] == ax[m].grid[n1+nt*n2] ); } } if ( okay ) ax[m].nsequ = ns; } } } qsort( ax, ndef, sizeof( ax_struct ), compar ); if ( ( ax[0].nsequ == (*nsubs) ) && ( ndef > 1 ) ) { ax_struct save; ax[0].nsequ = 1; save = ax[0]; for ( n = 1; n < ndef; n++ ) { ax[n-1] = ax[n]; } ax[ndef-1] = save; } count = (*nsubs); ax[0].ngrid = count / ax[0].nsequ; count /= ax[0].ngrid; for ( n = 0; n < ax[0].ngrid; n++ ) { ax[0].user[n] = ax[0].grid[n]; } for ( m = 1; m < ndef; m++ ) { ax[m].ngrid = ax[m-1].nsequ / ax[m].nsequ; count /= ax[m].ngrid; if ( m == ( ndef - 1 ) && count != 1 ) ax[m].ngrid *= count; for ( n = 0; n < ax[m].ngrid; n++ ) { ax[m].user[n] = ax[m].grid[n*((*nsubs)/ax[m-1].nsequ)]; } } for ( m = 0; m < ndef; m++ ) { char text[MAXSTRINGLEN]; int l = 0; int ndone = 0; SHIP( " " ); SHIP( ax[m].ctype ); for ( n = 1; n < ax[m].ngrid; n++ ) { ax[m].step[n] = ax[m].user[n] - ax[m].user[n-1]; } while ( ndone < ax[m].ngrid ) { l += sprintf( &text[l], " %d", ax[m].user[ndone++] ); for ( n = ndone+1; n < ax[m].ngrid && ax[m].step[ndone] == ax[m].step[n]; n++ ); if ( n > ( ndone + 1 ) ) { if ( ax[m].step[ndone] == 1 ) { l += sprintf( &text[l], ":%d", ax[m].user[n-1] ); } else if ( ax[m].step[ndone] == 0 ) { l += sprintf( &text[l], "::%d", n - ndone + 1 ); } else { l += sprintf( &text[l], ":%d:%d", ax[m].user[n-1], ax[m].step[ndone] ); } ndone = n; } } SHIP( text ); } RETURN( 0 ); } #if defined(TESTBED) #include "anyout.h" /* anyout_c */ #include "cancel.h" /* cancel_c */ #include "cmain.h" /* C program */ #include "finis.h" /* finis_c */ #include "init.h" /* init_c */ #include "dcdsetdef.h" /* dscset */ #include "usertext.h" /* usertext_c */ MAIN_PROGRAM_ENTRY { char message[100]; char textb[81]; dcdset_struct *r; fchar text; fint nsubs; fint output_level = 0; fint rs; fint *subsets = NULL; text.a = textb; text.l = sizeof( textb ) - 1; init_c( ); while ( 1 ) { fint input_level = 1; fint ninp; ninp = usertext_c( text, &input_level, tofchar( "INSET=" ), tofchar( "Enter set" ) ); cancel_c( tofchar( "INSET=" ) ); if ( ninp == 0 ) break; textb[ninp] = 0; r = dcdset( textb ); if ( r->status > 0 ) { nsubs = r->status; subsets = realloc( subsets, sizeof( fint ) * nsubs ); memmove( subsets, r->subsets, sizeof( fint ) * nsubs ); sprintf( message, "ORIGINAL: %.*s", nelc_c( text ), textb ); anyout_c( &output_level, tofchar( message ) ); rs = ecdset_c( text, tofchar( r->setname ), subsets, &nsubs ); if ( rs == 0 ) { sprintf( message, "ENCODED : %.*s", nelc_c( text ), textb ); anyout_c( &output_level, tofchar( message ) ); r = dcdset( textb ); if ( r->status == nsubs ) { fint n; fint okay; for ( okay =1, n = 0; n < nsubs; n++ ) { okay = ( r->subsets[n] == subsets[n] ); } if ( okay ) anyout_c( &output_level, tofchar( "OKAY" ) ); } } else { sprintf( message, "ecdset = %d", rs ); anyout_c( &output_level, tofchar( message ) ); } } } finis_c( ); return( 0 ); } #endif