A little bit complicated code which also dump comments on cols (based on Frosty code):
SELECT
dt.table_name, dt.column_name, dt.data_type, dt.data_length,
constr.r_tbl r_table, constr.r_col r_column,
comm.comments
FROM user_col_comments comm, user_tab_columns dt
LEFT OUTER JOIN (
SELECT
cons.table_name tbl,
cols.column_name col,
cons_r.table_name r_tbl,
cols_r.column_name r_col
FROM user_constraints cons
LEFT JOIN user_cons_columns cols ON cols.constraint_name = cons.constraint_name
LEFT JOIN user_constraints cons_r ON cons_r.constraint_name = cons.r_constraint_name
LEFT JOIN user_cons_columns cols_r ON cols_r.constraint_name = cons.r_constraint_name
WHERE cons.constraint_type = 'R'
) constr ON constr.tbl = dt.table_name AND constr.col = dt.column_name
WHERE dt.table_name = comm.table_name
AND dt.column_name = comm.column_name
ORDER BY dt.table_name, dt.column_name
;
To make output more readable I use break on TABLE_NAME; in sqlplus (look to my question http://stackoverflow.com/questions/14998296/print-only-first-unique-value-for-column-that-order-by-in-oracle-sqlplus/ ).