Commit 519f4b04 authored by Jody Goldberg's avatar Jody Goldberg Committed by Jody Goldberg

remove the rest of the CELLREF based productions.


2002-09-24  Jody Goldberg <jody@gnome.org>

	* src/parser.y : remove the rest of the CELLREF based productions.

	* src/parse-util.h : do a bit of tidying
	(col_parse) : make public.
	(row_parse) : make public.
	(cellpos_as_string) : rename from cell_pos_name.
	(cellpos_parse) : renamed from parse_cell_name
	(cellref_as_string) : rename from cellref_name
	(cellref_parse) : rename from cellref_get
	(parse_col_name) : delete duplicate
	(gnm_expr_char_start_p) : renamed from gnumeric_char_start_expr_p.

	* src/parse-util.c (rangeref_parse) : fix handling of non-3d
	  inter-sheet refs.
	(col_parse) : check for overflow.

	* src/parser.y : remove sheet_ref RANGEREF production. RANGEREF
	  already handles sheet references internally.

	* src/expr.c (gnm_expr_eval) : handle empties when implicit
	  intersection is valid but accesses an empty cell.
parent 09b2994f
2002-09-23 Jody Goldberg <jody@gnome.org>
2002-09-24 Jody Goldberg <jody@gnome.org>
* src/parser.y : remove the rest of the CELLREF based productions.
* src/parse-util.h : do a bit of tidying
(col_parse) : make public.
(row_parse) : make public.
(cellpos_as_string) : rename from cell_pos_name.
(cellpos_parse) : renamed from parse_cell_name
(cellref_as_string) : rename from cellref_name
(cellref_parse) : rename from cellref_get
(parse_col_name) : delete duplicate
(gnm_expr_char_start_p) : renamed from gnumeric_char_start_expr_p.
* src/parse-util.c (rangeref_parse) : fix handling of non-3d
inter-sheet refs.
(col_parse) : check for overflow.
* src/parser.y : remove sheet_ref RANGEREF production. RANGEREF
already handles sheet references internally.
* src/expr.c (gnm_expr_eval) : handle empties when implicit
intersection is valid but accesses an empty cell.
......
2002-09-23 Jody Goldberg <jody@gnome.org>
2002-09-24 Jody Goldberg <jody@gnome.org>
* src/parser.y : remove the rest of the CELLREF based productions.
* src/parse-util.h : do a bit of tidying
(col_parse) : make public.
(row_parse) : make public.
(cellpos_as_string) : rename from cell_pos_name.
(cellpos_parse) : renamed from parse_cell_name
(cellref_as_string) : rename from cellref_name
(cellref_parse) : rename from cellref_get
(parse_col_name) : delete duplicate
(gnm_expr_char_start_p) : renamed from gnumeric_char_start_expr_p.
* src/parse-util.c (rangeref_parse) : fix handling of non-3d
inter-sheet refs.
(col_parse) : check for overflow.
* src/parser.y : remove sheet_ref RANGEREF production. RANGEREF
already handles sheet references internally.
* src/expr.c (gnm_expr_eval) : handle empties when implicit
intersection is valid but accesses an empty cell.
......
2002-09-23 Jody Goldberg <jody@gnome.org>
2002-09-24 Jody Goldberg <jody@gnome.org>
* src/parser.y : remove the rest of the CELLREF based productions.
* src/parse-util.h : do a bit of tidying
(col_parse) : make public.
(row_parse) : make public.
(cellpos_as_string) : rename from cell_pos_name.
(cellpos_parse) : renamed from parse_cell_name
(cellref_as_string) : rename from cellref_name
(cellref_parse) : rename from cellref_get
(parse_col_name) : delete duplicate
(gnm_expr_char_start_p) : renamed from gnumeric_char_start_expr_p.
* src/parse-util.c (rangeref_parse) : fix handling of non-3d
inter-sheet refs.
(col_parse) : check for overflow.
* src/parser.y : remove sheet_ref RANGEREF production. RANGEREF
already handles sheet references internally.
* src/expr.c (gnm_expr_eval) : handle empties when implicit
intersection is valid but accesses an empty cell.
......
......@@ -748,6 +748,7 @@ plugins/fn-stat/Makefile
plugins/fn-string/Makefile
plugins/fn-random/Makefile
plugins/derivatives/Makefile
plugins/gnumeric_1_0/Makefile
plugins/sc/Makefile
plugins/sylk/Makefile
plugins/excel/Makefile
......
......@@ -48,7 +48,7 @@ omf: omf_timestamp
omf_timestamp: $(omffile)
-for file in $(omffile); do \
scrollkeeper-preinstall $(docdir)/`awk 'BEGIN {RS = ">" } /identifier/ {print $$0}' $${file} | awk 'BEGIN {FS="\""} /url/ {print $$2}'` $${file} $(omf_dir)/$${file}; \
scrollkeeper-preinstall $(docdir)/`awk 'BEGIN {RS = ">" } /identifier/ {print $$0}' $(srcdir)/$${file} | awk 'BEGIN {FS="\""} /url/ {print $$2}'` $(srcdir)/$${file} $(omf_dir)/$${file}; \
done
touch omf_timestamp
......
......@@ -765,7 +765,7 @@ applix_parse_cellref (ApplixReadState *state, unsigned char *buffer,
*sheet = applix_get_sheet (state, &buffer, separator);
/* Get cell addr */
if (*sheet && parse_cell_name (buffer, pos, FALSE, &len))
if (*sheet && cellpos_parse (buffer, pos, FALSE, &len))
return buffer + len;
*sheet = NULL;
......@@ -879,9 +879,10 @@ applix_read_view (ApplixReadState *state, unsigned char *buffer)
do {
int col, width;
char *tmp;
unsigned char dummy;
col = parse_col_name (tmp = ptr + 1, (char const **)&ptr);
if (tmp == ptr || col < 0 || *ptr != ':')
ptr = col_parse (tmp = ptr + 1, &col, &dummy);
if (tmp == ptr || *ptr != ':')
return applix_parse_error (state, "Invalid column");
width = strtol (tmp = ptr + 1, &ptr, 10);
if (tmp == ptr || width <= 0)
......
......@@ -108,6 +108,19 @@ char const *excel_builtin_formats[EXCEL_BUILTIN_FORMAT_LEN] = {
/* 0x31 */ "@"
};
static GIConv
excel_iconv_open_for_import (guint codepage)
{
if (codepage == 1200 || codepage == 1201)
/* this is 'compressed' unicode. unicode characters 0000->00FF
* which looks the same as 8859-1. What does Little endian vs
* bigendian have to do with this. There is only 1 byte, and it would
* certainly not be useful to keep the low byte as 0.
*/
return g_iconv_open ("UTF-8", "ISO-8859-1");
return gsf_msole_iconv_open_for_import (codepage);
}
static StyleFormat *
ms_excel_wb_get_fmt (ExcelWorkbook *wb, guint16 idx)
{
......@@ -2233,7 +2246,7 @@ ms_excel_sheet_shared_formula (ExcelSheet const *esheet,
{
g_return_val_if_fail (esheet != NULL, NULL);
d (5, printf ("FIND SHARED: %s\n", cell_pos_name (key)););
d (5, printf ("FIND SHARED: %s\n", cellpos_as_string (key)););
return g_hash_table_lookup (esheet->shared_formulae, key);
}
......@@ -3034,7 +3047,7 @@ ms_excel_read_selection (BiffQuery *q, ExcelSheet *esheet)
edit_pos.col = GSF_LE_GET_GUINT16 (q->data + 3);
d (5, printf ("Start selection\n"););
d (5, printf ("Cursor: %s in Ref #%d\n", cell_pos_name (&edit_pos),
d (5, printf ("Cursor: %s in Ref #%d\n", cellpos_as_string (&edit_pos),
j););
sv_selection_reset (sv);
......@@ -4755,7 +4768,7 @@ ms_excel_read_workbook (IOContext *context, WorkbookView *wb_view,
}
/* default to ansi in case the file does not contain a CODEPAGE record */
current_workbook_iconv = gsf_msole_iconv_open_for_import (1252);
current_workbook_iconv = excel_iconv_open_for_import (1252);
while (!stop_loading && /* we have not hit the end */
problem_loading == NULL && /* there were no problems so far */
......@@ -4873,7 +4886,7 @@ ms_excel_read_workbook (IOContext *context, WorkbookView *wb_view,
of currency amounts. */
guint16 const codepage = GSF_LE_GET_GUINT16 (q->data);
gsf_iconv_close (current_workbook_iconv);
current_workbook_iconv = gsf_msole_iconv_open_for_import (codepage);
current_workbook_iconv = excel_iconv_open_for_import (codepage);
d (0, {
switch (codepage) {
case 437:
......
......@@ -171,7 +171,7 @@ gnumeric_cell (FunctionEvalInfo *ei, Value **argv)
/* from CELL - limited usefulness! */
if (!g_ascii_strcasecmp(info_type, "address")) {
ParsePos pp;
char *ref_name = cellref_name (ref,
char *ref_name = cellref_as_string (ref,
parse_pos_init_evalpos (&pp, ei->pos), TRUE);
return value_new_string_nocopy (ref_name);
......@@ -183,7 +183,7 @@ gnumeric_cell (FunctionEvalInfo *ei, Value **argv)
if (tmp.sheet == NULL)
tmp.sheet = ei->pos->sheet;
ref_name = cellref_name (&tmp,
ref_name = cellref_as_string (&tmp,
parse_pos_init_evalpos (&pp, ei->pos), FALSE);
return value_new_string_nocopy (ref_name);
......
......@@ -256,13 +256,13 @@ excel_gb_range_new_ref (GBRunEvalContext *ec,
Range tmp;
int len;
if (!parse_cell_name (text, &tmp.start, FALSE, &len)) {
if (!cellpos_parse (text, &tmp.start, FALSE, &len)) {
gbrun_exception_firev (ec, "Invalid range '%s'", text);
return NULL;
}
if (text [len] == ':') {
if (!parse_cell_name (text + len + 1, &tmp.end, &tmp.end, TRUE, NULL)) {
if (!cellpos_parse (text + len + 1, &tmp.end, &tmp.end, TRUE, NULL)) {
gbrun_exception_firev (ec, "Invalid range '%s'", text);
return NULL;
}
......
......@@ -170,13 +170,13 @@ oleo_get_gnumeric_expr (char *g_expr, char const *o_expr,
end.col_relative = start.col_relative;
}
name = cellref_name (&start, cur_pos, TRUE);
name = cellref_as_string (&start, cur_pos, TRUE);
strcat (to, name);
g_free (name);
if (!cellref_equal (&start, &end)) {
strcat (to, ":");
name = cellref_name (&end, cur_pos, TRUE);
name = cellref_as_string (&end, cur_pos, TRUE);
strcat (to, name);
g_free (name);
}
......
......@@ -301,7 +301,7 @@ pln_get_addr (ParsePos const *pp, guint8 const *ch)
break;
}
return cellref_name (&ref, pp, TRUE);
return cellref_as_string (&ref, pp, TRUE);
}
static char *
......@@ -315,7 +315,7 @@ pln_convert_expr (ParsePos const *pp, guint8 const *ch)
/* Expressions are stored INFIX so it is easier to just generate text */
i = GSF_LE_GET_GUINT16 (ch); ch += 2;
#if DEBUG_EXPR
puts (cell_pos_name (&pp->eval));
puts (cellpos_as_string (&pp->eval));
gsf_mem_dump (ch, i);
#endif
for (end = ch + i ; ch < end ; ) {
......
......@@ -45,7 +45,7 @@ typedef enum {
} sc_string_cmd_t;
/* we can't use parse_cell_name b/c it doesn't support 0 bases (A0, B0, ...) */
/* we can't use cellpos_parse b/c it doesn't support 0 bases (A0, B0, ...) */
static gboolean
sc_cellname_to_coords (const char *cellname, int *col, int *row)
{
......@@ -218,7 +218,7 @@ sc_parse_cell_name_list (Sheet *sheet, const char *cell_name_str,
(!cell_name_str [i])){
buf [n] = '\0';
if (!parse_cell_name (buf, &pos)){
if (!cellpos_parse (buf, &pos)){
*error_flag = 1;
g_free (buf);
g_slist_free (cells);
......
......@@ -143,7 +143,7 @@ xml_sax_attr_cellpos (xmlChar const * const *attrs, char const *name, CellPos *v
if (strcmp (attrs[0], name))
return FALSE;
if (!parse_cell_name ((gchar *)attrs[1], val, TRUE, NULL)) {
if (!cellpos_parse ((gchar *)attrs[1], val, TRUE, NULL)) {
g_warning ("Invalid attribute '%s', expected cellpos, received '%s'",
name, attrs[1]);
return FALSE;
......@@ -1265,7 +1265,7 @@ xml_sax_finish_parse_wb_names_name (GsfXmlSAXState *gsf_state)
if (state->name.position) {
CellRef tmp;
char const *res;
res = cellref_get (&tmp, state->name.position, &pos.eval);
res = cellref_parse (&tmp, state->name.position, &pos.eval);
if (res != NULL && *res == '\0') {
pos.eval.col = tmp.col;
pos.eval.row = tmp.row;
......@@ -1312,7 +1312,7 @@ xml_sax_finish_parse_sheet_names_name (GsfXmlSAXState *gsf_state)
parse_pos_init (&pos, NULL, state->sheet, 0, 0);
if (state->name.position) {
CellRef tmp;
char const *res = cellref_get (&tmp, state->name.position, &pos.eval);
char const *res = cellref_parse (&tmp, state->name.position, &pos.eval);
if (res != NULL && *res == '\0') {
pos.eval.col = tmp.col;
pos.eval.row = tmp.row;
......
......@@ -679,7 +679,7 @@ static void
cb_cell_pool_leak (gpointer data, gpointer user)
{
Cell const *cell = data;
fprintf (stderr, "Leaking cell %p at %s\n", cell, cell_pos_name (&cell->pos));
fprintf (stderr, "Leaking cell %p at %s\n", cell, cellpos_as_string (&cell->pos));
}
#endif
......
......@@ -950,7 +950,7 @@ cmd_area_set_text_redo (GnumericCommand *cmd, WorkbookControl *wbc)
* 3) There is only one 1 selection
*/
l = me->selection;
start = gnumeric_char_start_expr_p (me->text);
start = gnm_expr_char_start_p (me->text);
if (start != NULL && me->as_array && l != NULL && l->next == NULL) {
expr = gnm_expr_parse_str_simple (start, &me->pp);
if (expr == NULL)
......@@ -3443,7 +3443,7 @@ cmd_search_replace_do_cell (CmdSearchReplace *me, EvalPos *ep,
* FIXME: this is a hack, but parse_text_value_or_expr
* does not have a better way of signaling an error.
*/
err = val && gnumeric_char_start_expr_p (cell_res.new_text);
err = val && gnm_expr_char_start_p (cell_res.new_text);
if (val) value_release (val);
if (expr) gnm_expr_unref (expr);
......
......@@ -1832,8 +1832,8 @@ dump_range_dep (gpointer key, gpointer value, gpointer closure)
Range const *range = &(deprange->range);
/* 2 calls to col_name and row_name. It uses a static buffer */
printf ("\t%s:", cell_pos_name (&range->start));
printf ("%s <- ", cell_pos_name (&range->end));
printf ("\t%s:", cellpos_as_string (&range->start));
printf ("%s <- ", cellpos_as_string (&range->end));
dep_collection_foreach_list (deprange->deps, list,
dump_dependent_list (list););
......@@ -1844,7 +1844,7 @@ dump_single_dep (gpointer key, gpointer value, gpointer closure)
{
DependencySingle *depsingle = key;
printf ("\t%s <- ", cell_pos_name (&depsingle->pos));
printf ("\t%s <- ", cellpos_as_string (&depsingle->pos));
dep_collection_foreach_list (depsingle->deps, list,
dump_dependent_list (list););
......
......@@ -125,7 +125,7 @@ value_at (ETableModel *etc, int col, int row, void *data)
break;
case COL_CELL:
result = e_utf8_from_locale_string (cell_pos_name (&item->ep.eval));
result = e_utf8_from_locale_string (cellpos_as_string (&item->ep.eval));
break;
case COL_TYPE:
......
......@@ -987,7 +987,9 @@ gnm_expr_eval (GnmExpr const *expr, EvalPos const *pos,
}
}
if (found) {
Cell * cell = sheet_cell_get (pos->sheet, c, r);
Cell * cell = sheet_cell_get (
eval_sheet (ref_a->sheet, pos->sheet),
c, r);
if (cell == NULL)
return handle_empty (NULL, flags);
......@@ -1180,7 +1182,7 @@ do_expr_as_string (GnmExpr const *expr, ParsePos const *pp,
return g_strdup (expr->name.name->name->str);
case GNM_EXPR_OP_CELLREF:
return cellref_name (&expr->cellref.ref, pp, FALSE);
return cellref_as_string (&expr->cellref.ref, pp, FALSE);
case GNM_EXPR_OP_CONSTANT: {
char *res;
......@@ -1306,7 +1308,7 @@ cellref_relocate (CellRef *ref, GnmExprRelocateInfo const *rinfo)
if (ref->row_relative)
row += rinfo->pos.eval.row;
/* fprintf (stderr, "%s\n", cellref_name (ref, &rinfo->pos, FALSE)); */
/* fprintf (stderr, "%s\n", cellref_as_string (ref, &rinfo->pos, FALSE)); */
/* All references should be valid initially. We assume that later. */
if (col < 0 || col >= SHEET_MAX_COLS ||
......
......@@ -332,7 +332,7 @@ entry_changed (GnumericExprEntry *ignore, void *data)
ItemEdit *item_edit = ITEM_EDIT (item);
char const *text = gtk_entry_get_text (item_edit->entry);
if (gnumeric_char_start_expr_p (text))
if (gnm_expr_char_start_p (text))
scan_for_range (item_edit, text);
gnome_canvas_item_request_update (item);
......
......@@ -59,6 +59,53 @@ col_name_internal (char *buf, int col)
return buf;
}
char const *
col_name (int col)
{
static char buffer [3]; /* What if SHEET_MAX_COLS is changed ? */
char *res = col_name_internal (buffer, col);
*res = '\0';
return buffer;
}
char const *
cols_name (int start_col, int end_col)
{
static char buffer [16]; /* Why is this 16 ? */
char *res = col_name_internal (buffer, start_col);
if (start_col != end_col) {
*res = ':';
res = col_name_internal (res + 1, end_col);
}
*res = '\0';
return buffer;
}
char const *
col_parse (char const *str, int *res, unsigned char *relative)
{
char const *ptr = str;
int col = -1;
if (!(*relative = (*ptr != '$')))
ptr++;
for (; col < SHEET_MAX_COLS ; ptr++)
if (('a' <= *ptr && *ptr <= 'z'))
col = 26 * (col + 1) + (*ptr - 'a');
else if (('A' <= *ptr && *ptr <= 'Z'))
col = 26 * (col + 1) + (*ptr - 'A');
else if (ptr != str) {
*res = col;
return ptr;
} else
return str;
return str;
}
/***************************************************************************/
inline static char *
row_name_internal (char *buf, int row)
{
......@@ -66,6 +113,30 @@ row_name_internal (char *buf, int row)
return buf + len;
}
char const *
row_name (int row)
{
static char buffer [6]; /* What if SHEET_MAX_ROWS changes? */
char *res = row_name_internal (buffer, row);
*res = '\0';
return buffer;
}
char const *
rows_name (int start_row, int end_row)
{
static char buffer [13]; /* What if SHEET_MAX_ROWS changes? */
char *res = row_name_internal (buffer, start_row);
if (start_row != end_row) {
*res = ':';
res = row_name_internal (res + 1, end_row);
}
*res = '\0';
return buffer;
}
/***************************************************************************/
inline static int
cellref_abs_col (CellRef const *ref, ParsePos const *pp)
......@@ -91,6 +162,74 @@ cellref_abs_row (CellRef const *ref, ParsePos const *pp)
return row;
}
/**
* cellref_as_string :
* @ref :
* @pp :
* @no_sheetname :
*
* Returns a string that the caller needs to free containing the A1 format
* representation of @ref as evaluated at @pp. @no_sheetname can be used to
* suppress the addition of the sheetname for non-local references.
**/
char *
cellref_as_string (CellRef const *cell_ref, ParsePos const *pp, gboolean no_sheetname)
{
static char buffer [sizeof (long) * 4 + 4];
char *p = buffer;
int col, row;
Sheet *sheet = cell_ref->sheet;
if (cell_ref->col_relative)
col = pp->eval.col + cell_ref->col;
else {
*p++ = '$';
col = cell_ref->col;
}
/* ICK! XL compatibility kludge */
col %= SHEET_MAX_COLS;
if (col < 0)
col += SHEET_MAX_COLS;
if (col <= 'Z'-'A') {
*p++ = col + 'A';
} else {
int a = col / ('Z'-'A'+1);
int b = col % ('Z'-'A'+1);
*p++ = a + 'A' - 1;
*p++ = b + 'A';
}
if (cell_ref->row_relative)
row = pp->eval.row + cell_ref->row;
else {
*p++ = '$';
row = cell_ref->row;
}
/* ICK! XL compatibility kludge */
row %= SHEET_MAX_ROWS;
if (row < 0)
row += SHEET_MAX_ROWS;
sprintf (p, "%d", row+1);
/* If it is a non-local reference, add the path to the external sheet */
if (sheet != NULL && !no_sheetname) {
if (pp->wb == NULL && pp->sheet == NULL) {
/* For the expression leak printer. */
return g_strconcat ("'?'|", buffer, NULL);
}
if (pp->wb == NULL || sheet->workbook == pp->wb)
return g_strconcat (sheet->name_quoted, "!", buffer, NULL);
return g_strconcat ("[", sheet->workbook->filename, "]",
sheet->name_quoted, "!", buffer, NULL);
} else
return g_strdup (buffer);
}
/**
* rangeref_as_string :
* @ref :
......@@ -169,65 +308,6 @@ rangeref_as_string (RangeRef const *ref, ParsePos const *pp)
}
}
/* Can remove sheet since local references have NULL sheet */
char *
cellref_name (CellRef const *cell_ref, ParsePos const *pp, gboolean no_sheetname)
{
static char buffer [sizeof (long) * 4 + 4];
char *p = buffer;
int col, row;
Sheet *sheet = cell_ref->sheet;
if (cell_ref->col_relative)
col = pp->eval.col + cell_ref->col;
else {
*p++ = '$';
col = cell_ref->col;
}
/* ICK! XL compatibility kludge */
col %= SHEET_MAX_COLS;
if (col < 0)
col += SHEET_MAX_COLS;
if (col <= 'Z'-'A') {
*p++ = col + 'A';
} else {
int a = col / ('Z'-'A'+1);
int b = col % ('Z'-'A'+1);
*p++ = a + 'A' - 1;
*p++ = b + 'A';
}
if (cell_ref->row_relative)
row = pp->eval.row + cell_ref->row;
else {
*p++ = '$';
row = cell_ref->row;
}
/* ICK! XL compatibility kludge */
row %= SHEET_MAX_ROWS;
if (row < 0)
row += SHEET_MAX_ROWS;
sprintf (p, "%d", row+1);
/* If it is a non-local reference, add the path to the external sheet */
if (sheet != NULL && !no_sheetname) {
if (pp->wb == NULL && pp->sheet == NULL) {
/* For the expression leak printer. */
return g_strconcat ("'?'|", buffer, NULL);
}
if (pp->wb == NULL || sheet->workbook == pp->wb)
return g_strconcat (sheet->name_quoted, "!", buffer, NULL);
return g_strconcat ("[", sheet->workbook->filename, "]",
sheet->name_quoted, "!", buffer, NULL);
} else
return g_strdup (buffer);
}
static char const *
cellref_a1_get (CellRef *out, char const *in, CellPos const *pos)
{
......@@ -364,7 +444,7 @@ cellref_r1c1_get (CellRef *out, char const *in, CellPos const *pos)
}
/**
* cellref_get:
* cellref_parse:
* @out: destination CellRef
* @in: reference description text, no leading
* whitespace allowed.
......@@ -375,7 +455,7 @@ cellref_r1c1_get (CellRef *out, char const *in, CellPos const *pos)
* Return value: TRUE if no format errors found.
**/
char const *
cellref_get (CellRef *out, char const *in, CellPos const *pos)
cellref_parse (CellRef *out, char const *in, CellPos const *pos)
{
char const *res;
......@@ -390,96 +470,6 @@ cellref_get (CellRef *out, char const *in, CellPos const *pos)
/****************************************************************************/
/**
* gnumeric_char_start_expr_p :
*
* Can the supplied string be an expression ? It does not guarantee that it is,
* however, it is possible. If it is possible it strips off any header
* characters that are not relevant.
*
* NOTE : things like -1,234 will match
*/
char const *
gnumeric_char_start_expr_p (char const * c)
{
char c0;
if (NULL == c)
return NULL;
c0 = *c;
if (c0 == '=' || c0 == '@' || (c0 == '+' && c[1] == 0))
return c + 1;
if ((c0 == '-' || c0 == '+') && c0 != c[1]) {
char *end;
/*
* Ok, we have a string that
* 1. starts with a sign
* 2. does not start with the sign repeated (think --------)
* 3. is more than one character
*
* Now we check whether we have a number. We don't want
* numbers to be treated as formulae. FIXME: this really
* just checks for C-syntax numbers.
*/
errno = 0;
(void) strtognum (c, &end);
if (errno || *end != 0 || end == c)
return (c0 == '+') ? c + 1 : c;
/* Otherwise, it's a number. */
}
return NULL;
}
char const *
col_name (int col)