Task: Range expansion

C: #include <stdio.h>
#include <stdlib.h>
#include <ctype.h>



int get_list(const char *, char **);
int get_rnge(const char *, char **);


void add_number(int x);
int add_range(int x, int y);

#define skip_space while(isspace(*s)) s++
#define get_number(x, s, e) (x = strtol(s, e, 10), *e != s)
int get_list(const char *s, char **e)
{
	int x;
	while (1) {
		skip_space;
		if (!get_rnge(s, e) && !get_number(x, s, e)) break;
		s = *e;

		skip_space;
		if ((*s) == '\0') { putchar('\n'); return 1; }
		if ((*s) == ',')  { s++; continue; }
		break;
	}
	*(const char **)e = s;
	printf("\nSyntax error at %s\n", s);
	return 0;
}

int get_rnge(const char *s, char **e)
{
	int x, y;
	char *ee;
	if (!get_number(x, s, &ee)) return 0;
	s = ee;

	skip_space;
	if (*s != '-') {
		*(const char **)e = s;
		return 0;
	}
	s++;
	if(!get_number(y, s, e)) return 0;
	return add_range(x, y);
}

void add_number(int x)
{
	printf("%d ", x);
}

int add_range(int x, int y)
{
	if (y <= x) return 0;
	while (x <= y) printf("%d ", x++);
	return 1;
}

int main()
{
	char *end;

	
	if (get_list("-6,-3--1,3-5,7-11,14,15,17-20", &end)) puts("Ok");

	
	get_list("-6 -3--1,3-5,7-11,14,15,17-20", &end);

	return 0;
}










Fortran:       MODULE HOMEONTHERANGE
       CONTAINS	
        CHARACTER*200 FUNCTION ERANGE(TEXT)	
Can't return a character value of variable size.
         CHARACTER*(*) TEXT	
         CHARACTER*200 ALINE	
         INTEGER N,N1,N2	
         INTEGER I,I1		
          ALINE = ""		
          L = 0			
          I = 1			
          CALL FORASIGN		
Chug through another number or number - number range.
        R:DO WHILE(EATINT(N1))	
            N2 = N1			
            IF (PASSBY("-")) CALL EATINT(N2)	
            IF (L.GT.0) CALL EMIT(",")		
            DO N = N1,N2,SIGN(+1,N2 - N1)	
              CALL SPLOT(N)				
              IF (N.NE.N2) CALL EMIT(",")		
            END DO				
            IF (.NOT.PASSBY(",")) EXIT R	
          END DO R		
Completed the scan. Just return the result.
          ERANGE = ALINE(1:L)	
         CONTAINS	
          SUBROUTINE FORASIGN	
    1       IF (I.LE.LEN(TEXT)) THEN	
              IF (TEXT(I:I).LE." ") THEN	
                I = I + 1				
                GO TO 1					
              END IF			
            END IF			
          END SUBROUTINE FORASIGN	

          LOGICAL FUNCTION PASSBY(C)	
Could consider or ignore case for letters, but this is really for single symbols.
           CHARACTER*1 C	
            PASSBY = .FALSE.	
            IF (I.LE.LEN(TEXT)) THEN	
              IF (TEXT(I:I).EQ.C) THEN	
                PASSBY = .TRUE.		
                I = I + 1		
                CALL FORASIGN		
              END IF		
            END IF		
          END FUNCTION PASSBY	

          LOGICAL FUNCTION EATINT(N)	
           INTEGER N	
           INTEGER D	
           LOGICAL NEG	
            EATINT = .FALSE.	
            IF (I.GT.LEN(TEXT)) RETURN	
            N = 0			
            IF (PASSBY("+")) THEN	
              NEG = .FALSE.		
             ELSE			
              NEG = PASSBY("-")		
            END IF			
            IF (I.GT.LEN(TEXT)) RETURN	
Chug through digits. Can develop -2147483648, thanks to the workings of two's complement.
   10       D = ICHAR(TEXT(I:I)) - ICHAR("0")	
            IF (0.LE.D .AND. D.LE.9) THEN	
              N = N*10 + D			
              I = I + 1				
              IF (I.LE.LEN(TEXT)) GO TO 10	
            END IF			
            IF (NEG) N = -N		
            EATINT = .TRUE.		
            CALL FORASIGN		
          END FUNCTION EATINT	

          SUBROUTINE EMIT(C)	
           CHARACTER*1 C	
            L = L + 1		
            IF (L.GT.LEN(ALINE)) STOP "Ran out of ALINE
            ALINE(L:L) = C	
          END SUBROUTINE EMIT	

          SUBROUTINE SPLOT(N)	
           INTEGER N		
           CHARACTER*12 FIELD	
           INTEGER I		
            WRITE (FIELD,"(I0)") N	
            DO I = 1,12		
              IF (FIELD(I:I).LE." ") EXIT	
              CALL EMIT(FIELD(I:I))	
            END DO		
          END SUBROUTINE SPLOT	
        END FUNCTION ERANGE	
      END MODULE HOMEONTHERANGE

      PROGRAM POKE
      USE HOMEONTHERANGE
      CHARACTER*(200) SOME
      SOME = "-6,-3--1,3-5,7-11,14,15,17-20"
      SOME = ERANGE(SOME)
      WRITE (6,*) SOME	
      END