static void *BuildList( void **array, unsigned next_offset, unsigned length ) /*******************************************************************************/ { void *list; void **owner; list = NULL; owner = &list; for( ; length != 0; --length ) { *owner = *array; _NEXT( *owner, next_offset ) = NULL; owner = &_NEXT( *owner, next_offset ); ++array; } return( list ); }
static void *MergeList( void *list1, void *list2, unsigned next_offset, bool (*before)(void *,void *) ) { /***************************************************************/ void *list; void *next; void **owner; list = NULL; owner = &list; while( list1 != NULL && list2 != NULL ) { if( (*before)( list1, list2 ) ) { *owner = list1; owner = &_NEXT( list1, next_offset ); next = _NEXT( list1, next_offset ); _NEXT( list1, next_offset ) = NULL; list1 = next; } else { *owner = list2; owner = &_NEXT( list2, next_offset ); next = _NEXT( list2, next_offset ); _NEXT( list2, next_offset ) = NULL; list2 = next; } } if( list1 != NULL ) { *owner = list1; } else if ( list2 != NULL ) { *owner = list2; } return( list ); }
static void *DoSortList( void *list, unsigned next_offset, bool (*before)(void *,void *), unsigned length ) { /**************************************************************************/ void **array; void **parray; void *list2; unsigned mid; int i; if( list == NULL ) return( NULL ); array = CGAlloc( length * sizeof( void * ) ); if( array == NULL ) { mid = length / 2; if( mid == 0 ) return( list ); /* FATAL ERROR! */ list2 = list; for( i = mid; i > 0; --i ) { list2 = _NEXT( list2, next_offset ); } list = DoSortList( list, next_offset, before, mid ); list2 = DoSortList( list2, next_offset, before, length - mid ); list = MergeList( list, list2, next_offset, before ); } else { list2 = list; parray = array; for( i = length; i > 0; --i ) { *parray++ = list2; list2 = _NEXT( list2, next_offset ); } ShellSort( array, length, before ); list = BuildList( array, next_offset, length ); CGFree( array ); } return( list ); }
extern void *SortList( void *list, unsigned next_offset, bool (*before)(void *,void *) ) { /****************************************************************/ void *list2; unsigned length; mem_out_action old_memout; length = 0; for( list2 = list; list2 != NULL; list2 = _NEXT( list2, next_offset ) ) { ++length; } if( length > 1 ) { old_memout = SetMemOut( MO_OK ); list = DoSortList( list, next_offset, before, length ); SetMemOut( old_memout ); } return( list ); }
// TODO mostly incomplete. Python parser only depends on %d and %s, so this // is mostly placeholder code. static int _v_printf(const char *fmt, va_list ap, writer_t writer, const void *warg) { // Bytes transmitted int count = 0; format_t f = { .width = 0, .precision = 0, .alternate = 0, .zeropad = 0, .leftjustify = 0, .spacepad = 0, .sign = 0, }; char c; // _NEXT returns on end of string. while (1) { _NEXT(fmt); if (c != '%') { // Literal character writer(warg, c); count++; continue; } _NEXT(fmt); if (c == '%') { // Literal % writer(warg, c); count++; continue; } // Flags char getflags = 0; do { switch (c) { case '#': // Alternate form f.alternate = 1; _NEXT(fmt); break; case '0': // Zero-pad f.zeropad = 1; _NEXT(fmt); break; case '-': // Left-justify f.leftjustify = 1; _NEXT(fmt); break; case ' ': // Pad positive sign with space f.spacepad = 1; _NEXT(fmt); break; case '+': // Force sign f.sign = 1; _NEXT(fmt); break; default: getflags = 0; } } while (getflags); // Field width if (isdigit(c) && c != '0') { // From string f.width = (int)strtol(fmt - 1, (char **)(&fmt), 10); // Updates fmt _NEXT(fmt); } else if (c == '*') { // From arg f.width = va_arg(ap, int); _NEXT(fmt); } // Precision if (c == '.') { _NEXT(fmt); if (c == '*') { // From arg f.precision = va_arg(ap, int); _NEXT(fmt); } else { // From string