Here's Jack Parker's routine - as used in his excellent dbdiff2 program:
GLOBALS
DEFINE datatype ARRAY[40] OF CHAR(20), # for coltype conversions
datetype ARRAY[16] OF CHAR(11) # for coltype conversions
###########################################################################
# Convert coltype/length into an SQL descriptor string
###########################################################################
FUNCTION col_cnvrt(coltype, collength)
DEFINE coltype, collength, NONULL SMALLINT,
SQL_strg CHAR(40),
tmp_strg CHAR(4)
LET coltype = coltype + 1 # datatype[] is offset by one
LET NONULL = coltype/256 # if 256 then is NO NULLS
LET coltype = coltype MOD 256 # lose the NO NULLS determinator
LET SQL_strg = datatype[coltype]
CASE coltype # these types require special processing
WHEN 1 # char
LET tmp_strg = collength using "<<<<"
LET SQL_strg = SQL_strg clipped, " (", tmp_strg clipped, ")"
# SQL syntax supports float(n) - Informix ignores this
# WHEN 4 # float
# LET SQL_strg = SQL_strg clipped, " (", ")"
WHEN 6 # decimal
LET SQL_strg = SQL_strg clipped, " (", fix_nm(collength) clipped, ")"
# Syntax supports serial(starting_no) - starting_no is unavaliable
# WHEN 7 # serial
# LET SQL_strg = SQL_strg clipped, " (", ")"
WHEN 9 # money
LET SQL_strg = SQL_strg clipped, " (", fix_nm(collength) clipped, ")"
WHEN 11 # datetime
LET SQL_strg = SQL_strg clipped, " (", fix_dt(collength) clipped, ")"
WHEN 14 # varchar
LET SQL_strg = SQL_strg clipped, " (", fix_nm(collength) clipped, ")"
WHEN 15 # interval
LET SQL_strg = SQL_strg clipped, " (", fix_dt(collength) clipped, ")"
END CASE
IF NONULL THEN
LET SQL_strg = SQL_strg clipped, " NOT NULL"
END IF
RETURN SQL_strg
END FUNCTION
###########################################################################
# Turn collength into two numbers - return as string
###########################################################################
FUNCTION fix_nm(num)
DEFINE num integer,
strg CHAR(8),
i, j SMALLINT,
strg1, strg2 char(3)
LET i = num / 256
LET j = num MOD 256
LET strg1 = i using "<<<"
LET strg2 = j using "<<<"
LET strg = strg1 clipped, ", ", strg2 clipped
RETURN strg
END FUNCTION
###########################################################################
# Turn collength into meaningful date info - return as string
###########################################################################
FUNCTION fix_dt(num)
DEFINE num integer,
i, j SMALLINT,
strg CHAR(20)
LET i = ((num mod 16) mod 12) + 1 # offset again
LET j = ((num / 16) mod 12) + 1 # offset again
LET strg = datetype[j] clipped, " TO ", datetype[i] clipped
RETURN strg
END FUNCTION
###########################################################################
# Array initialization
###########################################################################
LET datatype[1] = "CHAR"
LET datatype[2] = "SMALLINT"
LET datatype[3] = "INTEGER"
LET datatype[4] = "FLOAT"
LET datatype[5] = "SMALLFLOAT"
LET datatype[6] = "DECIMAL"
LET datatype[7] = "SERIAL"
LET datatype[8] = "DATE"
LET datatype[9] = "MONEY"
LET datatype[10] = "UNKNOWN"
LET datatype[11] = "DATETIME"
LET datatype[12] = "BYTE"
LET datatype[13] = "TEXT"
LET datatype[14] = "VARCHAR"
LET datatype[15] = "INTERVAL"
LET datatype[16] = "UNKNOWN" # little room for growth
LET datatype[17] = "UNKNOWN"
LET datatype[18] = "UNKNOWN"
LET datatype[19] = "UNKNOWN"
LET datatype[20] = "UNKNOWN"
LET datetype[1] = "YEAR"
LET datetype[3] = "MONTH"
LET datetype[5] = "DAY"
LET datetype[7] = "HOUR"
LET datetype[9] = "MINUTE"
LET datetype[11] = "SECOND"
LET datetype[12] = "FRACTION(1)"
LET datetype[13] = "FRACTION(2)"
LET datetype[14] = "FRACTION(3)"
LET datetype[15] = "FRACTION(4)"
LET datetype[16] = "FRACTION(5)"