mirror of
https://github.com/MidnightCommander/mc
synced 2024-12-23 12:56:51 +03:00
355 lines
7.0 KiB
C
355 lines
7.0 KiB
C
/*--------------------------------*-C-*---------------------------------*
|
|
* File: sltoken.c
|
|
*
|
|
* Descript: ---
|
|
*
|
|
* Requires: ---
|
|
*
|
|
* Public: SLexpand_escaped_char ();
|
|
* SLexpand_escaped_string ();
|
|
* SLang_extract_token ();
|
|
* SLang_guess_type ();
|
|
* SLatoi ();
|
|
*
|
|
* Private: ---
|
|
*
|
|
* Notes: ---
|
|
*
|
|
* Copyright (c) 1992, 1995 John E. Davis
|
|
* All rights reserved.
|
|
*
|
|
* You may distribute under the terms of either the GNU General Public
|
|
* License or the Perl Artistic License.
|
|
\*----------------------------------------------------------------------*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
#ifdef HAVE_STDLIB_H
|
|
# include <stdlib.h>
|
|
#endif
|
|
#include <string.h>
|
|
#include "_slang.h"
|
|
|
|
/* There are non-zeros at positions "\t %()*,/:;[]{}" */
|
|
|
|
static const unsigned char special_chars[256] =
|
|
{
|
|
/* 0 */ 0,0,0,0,0,0,0,0, 0,'\t',0,0,0,0,0,0,
|
|
/* 16 */ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
|
|
/* 32 */ ' ',0,0,0,0,'%',0,0, '(',')','*',0,',',0,0,'/',
|
|
/* 48 */ 0,0,0,0,0,0,0,0, 0,0,':',';',0,0,0,0,
|
|
/* 64 */ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
|
|
/* 80 */ 0,0,0,0,0,0,0,0, 0,0,0,'[',0,']',0,0,
|
|
/* 96 */ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
|
|
/* 112 */ 0,0,0,0,0,0,0,0, 0,0,0,'{',0,'}',0,0,
|
|
/* 8-bit characters */
|
|
/* 128 */ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
|
|
/* 144 */ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
|
|
/* 160 */ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
|
|
/* 176 */ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
|
|
/* 192 */ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
|
|
/* 208 */ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
|
|
/* 224 */ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
|
|
/* 240 */ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0
|
|
};
|
|
|
|
char *SLexpand_escaped_char(char *p, char *ch)
|
|
{
|
|
int i = 0;
|
|
int max = 0, num, base = 0;
|
|
char ch1;
|
|
|
|
ch1 = *p++;
|
|
|
|
switch (ch1)
|
|
{
|
|
default: num = ch1; break;
|
|
case 'n': num = '\n'; break;
|
|
case 't': num = '\t'; break;
|
|
case 'v': num = '\v'; break;
|
|
case 'b': num = '\b'; break;
|
|
case 'r': num = '\r'; break;
|
|
case 'f': num = '\f'; break;
|
|
case 'E': case 'e': num = 27; break;
|
|
case 'a': num = 7;
|
|
break;
|
|
|
|
/* octal */
|
|
case '0': case '1': case '2': case '3':
|
|
case '4': case '5': case '6': case '7':
|
|
max = '7';
|
|
base = 8; i = 2; num = ch1 - '0';
|
|
break;
|
|
|
|
case 'd': /* decimal -- S-Lang extension */
|
|
base = 10;
|
|
i = 3;
|
|
max = '9';
|
|
num = 0;
|
|
break;
|
|
|
|
case 'x': /* hex */
|
|
base = 16;
|
|
max = '9';
|
|
i = 2;
|
|
num = 0;
|
|
break;
|
|
}
|
|
|
|
while (i--)
|
|
{
|
|
ch1 = *p;
|
|
|
|
if ((ch1 <= max) && (ch1 >= '0'))
|
|
{
|
|
num = base * num + (ch1 - '0');
|
|
}
|
|
else if (base == 16)
|
|
{
|
|
ch1 |= 0x20;
|
|
if ((ch1 < 'a') || ((ch1 > 'f'))) break;
|
|
num = base * num + 10 + (ch1 - 'a');
|
|
}
|
|
else break;
|
|
p++;
|
|
}
|
|
|
|
*ch = (char) num;
|
|
return p;
|
|
}
|
|
|
|
void SLexpand_escaped_string (register char *s, register char *t,
|
|
register char *tmax)
|
|
{
|
|
char ch;
|
|
|
|
while (t < tmax)
|
|
{
|
|
ch = *t++;
|
|
if (ch == '\\')
|
|
{
|
|
t = SLexpand_escaped_char (t, &ch);
|
|
}
|
|
*s++ = ch;
|
|
}
|
|
*s = 0;
|
|
}
|
|
|
|
|
|
int SLang_extract_token (char **linep, char *word_parm, int byte_comp)
|
|
{
|
|
register char ch, *line, *word = word_parm;
|
|
int string;
|
|
char ch1;
|
|
char *word_max;
|
|
|
|
word_max = word + 250;
|
|
|
|
line = *linep;
|
|
|
|
/* skip white space */
|
|
while (((ch = *line) == ' ')
|
|
|| (ch == '\t')) line++;
|
|
|
|
if ((!ch) || (ch == '\n'))
|
|
{
|
|
*linep = line;
|
|
return(0);
|
|
}
|
|
|
|
*word++ = ch;
|
|
line++;
|
|
|
|
/* Look for -something and rule out --something and -= something */
|
|
if ((ch == '-') &&
|
|
(*line != '-') && (*line != '=') && ((*line > '9') || (*line < '0')))
|
|
{
|
|
*word = 0;
|
|
*linep = line;
|
|
return 1;
|
|
}
|
|
|
|
|
|
if (ch == '"') string = 1; else string = 0;
|
|
if (ch == '\'')
|
|
{
|
|
if ((ch = *line++) != 0)
|
|
{
|
|
if (ch == '\\')
|
|
{
|
|
line = SLexpand_escaped_char(line, &ch1);
|
|
ch = ch1;
|
|
}
|
|
if (*line++ == '\'')
|
|
{
|
|
--word;
|
|
sprintf(word, "%d", (int) ((unsigned char) ch));
|
|
word += strlen (word); ch = '\'';
|
|
}
|
|
else SLang_Error = SYNTAX_ERROR;
|
|
}
|
|
else SLang_Error = SYNTAX_ERROR;
|
|
}
|
|
else if (!special_chars[(unsigned char) ch])
|
|
{
|
|
while (ch = *line++,
|
|
(ch > '"') ||
|
|
((ch != '\n') && (ch != 0) && (ch != '"')))
|
|
{
|
|
if (string)
|
|
{
|
|
if (ch == '\\')
|
|
{
|
|
ch = *line++;
|
|
if ((ch == 0) || (ch == '\n')) break;
|
|
if (byte_comp) *word++ = '\\';
|
|
else
|
|
{
|
|
line = SLexpand_escaped_char(line - 1, &ch1);
|
|
ch = ch1;
|
|
}
|
|
}
|
|
}
|
|
else if (special_chars[(unsigned char) ch])
|
|
{
|
|
line--;
|
|
break;
|
|
}
|
|
|
|
*word++ = ch;
|
|
if (word > word_max)
|
|
{
|
|
SLang_doerror ("Token to large.");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ((!ch) || (ch == '\n')) line--;
|
|
if ((ch == '"') && string) *word++ = '"'; else if (string) SLang_Error = SYNTAX_ERROR;
|
|
*word = 0;
|
|
*linep = line;
|
|
/* massage variable-- and ++ into --variable, etc... */
|
|
if (((int) (word - word_parm) > 2)
|
|
&& (ch = *(word - 1), (ch == '+') || (ch == '-'))
|
|
&& (ch == *(word - 2)))
|
|
{
|
|
word--;
|
|
while (word >= word_parm + 2)
|
|
{
|
|
*word = *(word - 2);
|
|
word--;
|
|
}
|
|
*word-- = ch;
|
|
*word-- = ch;
|
|
}
|
|
return(1);
|
|
}
|
|
|
|
|
|
int SLang_guess_type (char *t)
|
|
{
|
|
char *p;
|
|
register char ch;
|
|
|
|
if (*t == '-') t++;
|
|
p = t;
|
|
#ifdef FLOAT_TYPE
|
|
if (*p != '.')
|
|
{
|
|
#endif
|
|
while ((*p >= '0') && (*p <= '9')) p++;
|
|
if (t == p) return(STRING_TYPE);
|
|
if ((*p == 'x') && (p == t + 1)) /* 0x?? */
|
|
{
|
|
p++;
|
|
while (ch = *p,
|
|
((ch >= '0') && (ch <= '9'))
|
|
|| (((ch | 0x20) >= 'a') && ((ch | 0x20) <= 'f'))) p++;
|
|
}
|
|
if (*p == 0) return(INT_TYPE);
|
|
#ifndef FLOAT_TYPE
|
|
return(STRING_TYPE);
|
|
#else
|
|
}
|
|
|
|
/* now down to float case */
|
|
if (*p == '.')
|
|
{
|
|
p++;
|
|
while ((*p >= '0') && (*p <= '9')) p++;
|
|
}
|
|
if (*p == 0) return(FLOAT_TYPE);
|
|
if ((*p != 'e') && (*p != 'E')) return(STRING_TYPE);
|
|
p++;
|
|
if ((*p == '-') || (*p == '+')) p++;
|
|
while ((*p >= '0') && (*p <= '9')) p++;
|
|
if (*p != 0) return(STRING_TYPE); else return(FLOAT_TYPE);
|
|
#endif
|
|
}
|
|
|
|
int SLatoi (unsigned char *s)
|
|
{
|
|
register unsigned char ch;
|
|
register unsigned int value;
|
|
register int base;
|
|
|
|
if (*s != '0') return atoi((char *) s);
|
|
|
|
/* look for 'x' which indicates hex */
|
|
s++;
|
|
if ((*s | 0x20) == 'x')
|
|
{
|
|
base = 16;
|
|
s++;
|
|
if (*s == 0)
|
|
{
|
|
SLang_Error = SYNTAX_ERROR;
|
|
return -1;
|
|
}
|
|
}
|
|
else base = 8;
|
|
|
|
|
|
value = 0;
|
|
while ((ch = *s++) != 0)
|
|
{
|
|
char ch1 = ch | 0x20;
|
|
switch (ch1)
|
|
{
|
|
default:
|
|
SLang_Error = SYNTAX_ERROR;
|
|
break;
|
|
case '8':
|
|
case '9':
|
|
if (base != 16) SLang_Error = SYNTAX_ERROR;
|
|
/* drop */
|
|
case '0':
|
|
case '1':
|
|
case '2':
|
|
case '3':
|
|
case '4':
|
|
case '5':
|
|
case '6':
|
|
case '7':
|
|
ch1 -= '0';
|
|
break;
|
|
|
|
case 'a':
|
|
case 'b':
|
|
case 'c':
|
|
case 'd':
|
|
case 'e':
|
|
case 'f':
|
|
if (base != 16) SLang_Error = SYNTAX_ERROR;
|
|
ch1 = (ch1 - 'a') + 10;
|
|
break;
|
|
}
|
|
value = value * base + ch1;
|
|
}
|
|
return (int) value;
|
|
}
|