+ /*
+ * round up x to a multiple of y
+ * for computing offsets of aligned things.
+ * y had better be positive.
+ * rounding is in the direction of x.
+ */
+long
+roundup( x , y )
+ long x;
+ register long y;
+ {
+
+ if ( y == 0 ) {
+ return 0;
+ }
+ if ( x >= 0 ) {
+ return ( ( ( x + ( y - 1 ) ) / y ) * y );
+ } else {
+ return ( ( ( x - ( y - 1 ) ) / y ) * y );
+ }
+ }
+
+ /*
+ * alignment of an object using the c alignment scheme
+ */
+int
+align( np )
+ struct nl *np;
+ {
+ register struct nl *p;
+
+ p = np;
+ if ( p == NIL ) {
+ return 0;
+ }
+alignit:
+ switch ( p -> class ) {
+ case TYPE:
+ switch ( nloff( p ) ) {
+ case TNIL:
+ return A_POINT;
+ case TSTR:
+ return A_CHAR;
+ case TSET:
+ return A_SET;
+ default:
+ p = p -> type;
+ goto alignit;
+ }
+ case ARRAY:
+ /*
+ * arrays are aligned as their component types
+ */
+ p = p -> type;
+ goto alignit;
+ case PTR:
+ return A_POINT;
+ case FILET:
+ return A_FILET;
+ case RANGE:
+ if ( p -> type == nl+TDOUBLE ) {
+ return A_DOUBLE;
+ }
+ /* else, fall through */
+ case SCAL:
+ switch ( bytes( p -> range[0] , p -> range[1] ) ) {
+ case 4:
+ return A_LONG;
+ case 2:
+ return A_SHORT;
+ case 1:
+ return A_CHAR;
+ default:
+ panic( "align: scal" );
+ }
+ case SET:
+ return A_SET;
+ case STR:
+ return A_CHAR;
+ case RECORD:
+ /*
+ * follow chain through all fields in record,
+ * taking max of alignments of types of fields.
+ * short circuit out if i reach the maximum alignment.
+ * this is pretty likely, as A_MAX is only 4.
+ */
+ {
+ register long recalign;
+ register long fieldalign;
+
+ recalign = A_MIN;
+ p = p -> chain;
+ while ( ( p != NIL ) && ( recalign < A_MAX ) ) {
+ fieldalign = align( p -> type );
+ if ( fieldalign > recalign ) {
+ recalign = fieldalign;
+ }
+ p = p -> chain;
+ }
+ return recalign;
+ }
+ default:
+ panic( "align" );
+ }
+ }
+