~ubuntu-branches/ubuntu/karmic/remind/karmic

« back to all changes in this revision

Viewing changes to src/token.c

  • Committer: Bazaar Package Importer
  • Author(s): Javier Fernandez-Sanguino Pen~a
  • Date: 1999-02-19 13:36:15 UTC
  • Revision ID: james.westby@ubuntu.com-19990219133615-ovob95sord67b0ks
Tags: 03.00.22-1
* NMU upload, maintainer seems to be missing.
* Changed to main (now GPL) (Closes: #42402)
* New upstream version (Closes: #59447)
* Moved to use debconf.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************/
 
2
/*                                                             */
 
3
/*  TOKEN.C                                                    */
 
4
/*                                                             */
 
5
/*  Contains routines for parsing the reminder file and        */
 
6
/*  classifying the tokens parsed.                             */
 
7
/*                                                             */
 
8
/*  This file is part of REMIND.                               */
 
9
/*  Copyright (C) 1992-1998 by David F. Skoll                  */
 
10
/*  Copyright (C) 1999-2000 by Roaring Penguin Software Inc.   */
 
11
/*                                                             */
 
12
/***************************************************************/
 
13
 
 
14
#include "config.h"
 
15
static char const RCSID[] = "$Id: token.c,v 1.9 2000/02/18 03:46:10 dfs Exp $";
 
16
 
 
17
#include <stdio.h>
 
18
#include <string.h>
 
19
#include <ctype.h>
 
20
 
 
21
#ifdef HAVE_STDLIB_H
 
22
#include <stdlib.h>
 
23
#endif
 
24
 
 
25
#ifdef HAVE_MALLOC_H
 
26
#include <malloc.h>
 
27
#endif
 
28
 
 
29
#include "types.h"
 
30
#include "globals.h"
 
31
#include "protos.h"
 
32
#include "err.h"
 
33
 
 
34
/* The macro PARSENUM parses a char pointer as an integer.  It simply
 
35
   executes 'return' if an initial non-numeric char is found. */
 
36
#define PARSENUM(var, string) \
 
37
if (!isdigit(*(string))) return; \
 
38
var = 0; \
 
39
while (isdigit(*(string))) { \
 
40
    var *= 10; \
 
41
    var += *(string) - '0'; \
 
42
    string++; \
 
43
}
 
44
 
 
45
#define UPPER(c) (islower(c) ? toupper(c) : c)
 
46
 
 
47
/* The big array holding all recognized (literal) tokens in reminder file.
 
48
   Keep this array sorted, or software will not work. */
 
49
Token TokArray[] = {
 
50
    /* NAME          MINLEN      TYPE           VALUE */
 
51
 
 
52
    { "after",          3,      T_Skip,         AFTER_SKIP },
 
53
    { "april",          3,      T_Month,        3 },
 
54
    { "at",             2,      T_At,           0 },
 
55
    { "august",         3,      T_Month,        7 },
 
56
    { "banner",         3,      T_Banner,       0 },
 
57
    { "before",                 3,      T_Skip,         BEFORE_SKIP },
 
58
    { "cal",            3,      T_RemType,      CAL_TYPE },
 
59
    { "clear-omit-context", 5,   T_Clr,         0 },
 
60
    { "debug",          5,      T_Debug,       0 },
 
61
    { "december",       3,      T_Month,       11 },
 
62
    { "dumpvars",       4,      T_Dumpvars,    0 },
 
63
    { "duration",       3,      T_Duration,     0 },
 
64
    { "else",           4,      T_Else,         0 },
 
65
    { "endif",          5,      T_EndIf,        0 },
 
66
    { "errmsg",         6,      T_ErrMsg,      0 },
 
67
    { "exit",           4,      T_Exit,         0 },
 
68
    { "february",       3,      T_Month,        1 },
 
69
    { "flush",          5,      T_Flush,        0 },
 
70
    { "friday",         3,      T_WkDay,        4 },
 
71
    { "fset",           4,      T_Fset,         0 },
 
72
    { "if",             2,      T_If,           0 },
 
73
    { "iftrig",         6,      T_IfTrig,       0 },
 
74
    { "include",        3,      T_Include,      0 },
 
75
    { "january",        3,      T_Month,        0 },
 
76
    { "july",           3,      T_Month,        6 },
 
77
    { "june",           3,      T_Month,        5 },
 
78
    { "march",          3,      T_Month,        2 },
 
79
    { "may",            3,      T_Month,        4 },
 
80
    { "monday",         3,      T_WkDay,        0 },
 
81
    { "msf",            3,      T_RemType,      MSF_TYPE },
 
82
    { "msg",            3,      T_RemType,      MSG_TYPE },
 
83
    { "november",       3,      T_Month,        10 },
 
84
    { "october",        3,      T_Month,        9 },
 
85
    { "omit",           3,      T_Omit,         0 },
 
86
    { "once",           3,      T_Once,         0 },
 
87
    { "pop-omit-context", 3,    T_Pop,          0 },
 
88
    { "preserve",       8,      T_Preserve,     0 },
 
89
    { "priority",       8,      T_Priority,     0 },
 
90
    { "ps",             2,      T_RemType,      PS_TYPE },
 
91
    { "psfile",         6,      T_RemType,      PSF_TYPE },
 
92
    { "push-omit-context", 4,   T_Push,         0 },
 
93
    { "rem",            3,      T_Rem,          0 },
 
94
    { "run",            3,      T_RemType,      RUN_TYPE },
 
95
    { "satisfy",        7,      T_RemType,      SAT_TYPE },
 
96
    { "saturday",       3,      T_WkDay,        5 },
 
97
    { "scanfrom",       4,      T_Scanfrom,     0 },
 
98
    { "sched",          5,      T_Sched,        0 },
 
99
    { "september",      3,      T_Month,        8 },
 
100
    { "set",            3,      T_Set,          0 },
 
101
    { "skip",           3,      T_Skip,         SKIP_SKIP },
 
102
    { "special",        7,      T_RemType,      PASSTHRU_TYPE },
 
103
    { "sunday",         3,      T_WkDay,        6 },
 
104
    { "tag",            3,      T_Tag,          0 },
 
105
    { "thursday",       3,      T_WkDay,        3 },
 
106
    { "tuesday",        3,      T_WkDay,        1 },
 
107
    { "unset",          5,      T_UnSet,        0 },
 
108
    { "until",          3,      T_Until,        0 },
 
109
    { "warn",           4,      T_Warn,         0 },
 
110
    { "wednesday",      3,      T_WkDay,        2 }
 
111
};
 
112
 
 
113
/* If language != English, we must also search the following... */
 
114
#if LANG != ENGLISH
 
115
Token NonEnglishToks[] = {
 
116
    /* NAME          MINLEN      TYPE           VALUE */
 
117
 
 
118
    { L_MONDAY,        3,       T_WkDay,        0 },
 
119
    { L_TUESDAY,       3,       T_WkDay,        1 },
 
120
    { L_WEDNESDAY,     3,       T_WkDay,        2 },
 
121
    { L_THURSDAY,      3,       T_WkDay,        3 },
 
122
    { L_FRIDAY,        3,       T_WkDay,        4 },
 
123
    { L_SATURDAY,      3,       T_WkDay,        5 },
 
124
    { L_SUNDAY,        3,       T_WkDay,        6 },
 
125
    { L_JAN,           3,       T_Month,        0 },
 
126
    { L_FEB,           3,       T_Month,        1 },
 
127
    { L_MAR,           3,       T_Month,        2 },
 
128
    { L_APR,           3,       T_Month,        3 },
 
129
    { L_MAY,           3,       T_Month,        4 },
 
130
    { L_JUN,           3,       T_Month,        5 },
 
131
    { L_JUL,           3,       T_Month,        6 },
 
132
    { L_AUG,           3,       T_Month,        7 },
 
133
    { L_SEP,           3,       T_Month,        8 },
 
134
    { L_OCT,           3,       T_Month,        9 },
 
135
    { L_NOV,           3,       T_Month,        10 },
 
136
    { L_DEC,           3,       T_Month,        11 }
 
137
};
 
138
#endif
 
139
 
 
140
PRIVATE int TokStrCmp ARGS((const Token *t, const char *s));
 
141
 
 
142
/***************************************************************/
 
143
/*                                                             */
 
144
/*  FindInitialToken                                           */
 
145
/*                                                             */
 
146
/*  Find the initial token on the command line.  If it's a     */
 
147
/*  left square bracket, return a T_Illegal type.              */
 
148
/*                                                             */
 
149
/***************************************************************/
 
150
#ifdef HAVE_PROTOS
 
151
PUBLIC char *FindInitialToken(Token *tok, char *s)
 
152
#else
 
153
char *FindInitialToken(tok, s)
 
154
Token *tok;
 
155
char *s;
 
156
#endif
 
157
{
 
158
    DynamicBuffer buf;
 
159
    DBufInit(&buf);
 
160
 
 
161
    tok->type = T_Illegal;
 
162
 
 
163
    while (isspace(*s)) s++;
 
164
 
 
165
    while (*s && !isspace(*s)) {
 
166
        if (DBufPutc(&buf, *s++) != OK) return s;
 
167
    }
 
168
 
 
169
    FindToken(DBufValue(&buf), tok);
 
170
    DBufFree(&buf);
 
171
 
 
172
    return s;
 
173
}
 
174
     
 
175
 
 
176
/***************************************************************/
 
177
/*                                                             */
 
178
/*  FindToken                                                  */
 
179
/*                                                             */
 
180
/*  Given a string, which token is it?                         */
 
181
/*                                                             */
 
182
/***************************************************************/
 
183
#ifdef HAVE_PROTOS
 
184
PUBLIC void FindToken(const char *s, Token *tok)
 
185
#else
 
186
void FindToken(s, tok)
 
187
char *s;
 
188
Token *tok;
 
189
#endif
 
190
{
 
191
    register int top, bot, mid, r;
 
192
    int l;
 
193
 
 
194
    tok->type = T_Illegal;
 
195
    if (! *s) {
 
196
        tok->type = T_Empty;
 
197
        return;
 
198
    }
 
199
       
 
200
    if (*s == '#' || *s == ';') {
 
201
        tok->type = T_Comment;
 
202
        return;
 
203
    }
 
204
 
 
205
    /* Quickly give up the search if first char not a letter */
 
206
    if ( ! isalpha(*s)) {
 
207
        FindNumericToken(s, tok);
 
208
        return;
 
209
    }
 
210
 
 
211
    l = strlen(s);
 
212
 
 
213
    /* Ignore trailing commas */
 
214
    if (l > 0 && s[l-1] == ',') {
 
215
        l--;
 
216
    }
 
217
    bot = 0;
 
218
    top = sizeof(TokArray) / sizeof(TokArray[0]) - 1;
 
219
 
 
220
    while(top >= bot) {
 
221
        mid = (top + bot) / 2;
 
222
        r = TokStrCmp(&TokArray[mid], s);
 
223
        if (!r) {
 
224
            if (l >= TokArray[mid].MinLen) {
 
225
                tok->type = TokArray[mid].type;
 
226
                tok->val  = TokArray[mid].val;
 
227
                return;
 
228
            } else {
 
229
                while (mid && !TokStrCmp(&TokArray[mid-1],s)) mid--;
 
230
                while (!TokStrCmp(&TokArray[mid], s) && l < TokArray[mid].MinLen)
 
231
                    mid++;
 
232
                if (!TokStrCmp(&TokArray[mid], s)) {
 
233
                    tok->type = TokArray[mid].type;
 
234
                    tok->val = TokArray[mid].val;
 
235
                    return;
 
236
                }
 
237
            }
 
238
            break;
 
239
        }
 
240
        if (r > 0) top = mid-1; else bot=mid+1;
 
241
    }
 
242
 
 
243
/* If language is other than English, search the DayNames[] and MonthNames[]
 
244
   array. */
 
245
#if LANG != ENGLISH
 
246
    for (r=0; r<(sizeof(NonEnglishToks) / sizeof(Token)); r++) {
 
247
        if (l >= NonEnglishToks[r].MinLen && 
 
248
            !TokStrCmp(&NonEnglishToks[r], s)) {
 
249
            tok->type = NonEnglishToks[r].type;
 
250
            tok->val = NonEnglishToks[r].val;
 
251
            return;
 
252
        }
 
253
    }
 
254
#endif
 
255
 
 
256
    return;
 
257
}
 
258
 
 
259
/***************************************************************/
 
260
/*                                                             */
 
261
/*  FindNumericToken                                           */
 
262
/*                                                             */
 
263
/*  Parse a numeric token:                                     */
 
264
/*  Year - number between 1990 and 2085, or 90-99.             */
 
265
/*  Day - number between 1 and 31                              */
 
266
/*  Delta - +[+]n                                              */
 
267
/*  Back - -[-]n                                               */
 
268
/*  Rep - *n                                                   */
 
269
/*                                                             */
 
270
/***************************************************************/
 
271
#ifdef HAVE_PROTOS
 
272
PUBLIC void FindNumericToken(const char *s, Token *t)
 
273
#else
 
274
void FindNumericToken(s, t)
 
275
char *s;
 
276
Token *t;
 
277
#endif
 
278
{
 
279
    int mult = 1, hour, min;
 
280
 
 
281
    t->type = T_Illegal;
 
282
    t->val = 0;
 
283
    if (isdigit(*s)) {
 
284
        PARSENUM(t->val, s);
 
285
 
 
286
        /* If we hit a comma, swallow it.  This allows stuff
 
287
           like Jan 6, 1998 */
 
288
        if (*s == ',') {
 
289
            s++;
 
290
            /* Special hack - convert years between 90 and
 
291
               99 to 1990 and 1999 */
 
292
            if (t->val >= 90 && t->val <= 99) t->val += 1900;
 
293
 
 
294
            /* Classify the number we've got */
 
295
            if (t->val >= BASE && t->val <= BASE+YR_RANGE) t->type = T_Year;
 
296
            else if (t->val >= 1 && t->val <= 31) t->type = T_Day;
 
297
            else t->type = T_Number;
 
298
            return;
 
299
        }
 
300
        /* If we hit a colon or a period, we've probably got a time hr:min */
 
301
        if (*s == ':' || *s == '.' || *s == TIMESEP) {
 
302
            s++;
 
303
            hour = t->val;
 
304
            PARSENUM(min, s);
 
305
            if (*s || hour > 23 || min > 59) return;  /* Illegal time */
 
306
            t->val = hour*60 + min;  /* Convert to minutes past midnight */
 
307
            t->type = T_Time;
 
308
            return;
 
309
        }
 
310
 
 
311
        /* If we hit a non-digit, error! */
 
312
        if (*s) return;
 
313
 
 
314
        /* Special hack - convert years between 90 and 99 to 1990 and 1999 */
 
315
        if (t->val >= 90 && t->val <= 99) t->val += 1900;
 
316
 
 
317
        /* Classify the number we've got */
 
318
        if (t->val >= BASE && t->val <= BASE+YR_RANGE) t->type = T_Year;
 
319
        else if (t->val >= 1 && t->val <= 31) t->type = T_Day;
 
320
        else t->type = T_Number;
 
321
        return;
 
322
    } else if (*s == '*') {
 
323
        s++;
 
324
        PARSENUM(t->val, s);
 
325
        if (*s) return;  /* Illegal token if followed by non-numeric char */
 
326
        t->type = T_Rep;
 
327
        return;
 
328
    } else if (*s == '+') {
 
329
        s++;
 
330
        if (*s == '+') { mult = -1; s++; }
 
331
        PARSENUM(t->val, s);
 
332
        if (*s) return;  /* Illegal token if followed by non-numeric char */
 
333
        t->type = T_Delta;
 
334
        t->val *= mult;
 
335
        return;
 
336
    } else if (*s == '-') {
 
337
        s++;
 
338
        if (*s == '-') { mult = -1; s++; }
 
339
        PARSENUM(t->val, s);
 
340
        if (*s) return;  /* Illegal token if followed by non-numeric char */
 
341
        t->type = T_Back;
 
342
        t->val *= mult;
 
343
        return;
 
344
    }
 
345
    return;  /* Unknown token type */
 
346
}
 
347
 
 
348
 
 
349
/***************************************************************/
 
350
/*                                                             */
 
351
/*  TokStrCmp                                                  */
 
352
/*                                                             */
 
353
/*  Compare a token to a string.                               */
 
354
/*                                                             */
 
355
/***************************************************************/
 
356
#ifdef HAVE_PROTOS
 
357
PRIVATE int TokStrCmp(const Token *t, const char *s)
 
358
#else
 
359
static int TokStrCmp(t, s)
 
360
Token *t;
 
361
char *s;
 
362
#endif
 
363
{
 
364
    register int r;
 
365
    char *tk = t->name;
 
366
    while(*tk && *s && !(*s == ',' && *(s+1) == 0)) {
 
367
        r = UPPER(*tk) - UPPER(*s);
 
368
        tk++;
 
369
        s++;
 
370
        if (r) return r;
 
371
    }
 
372
    /* Ignore trailing commas on s */
 
373
 
 
374
    if (!*s || (*s == ',' && !*(s+1))) return 0;
 
375
    return (*tk - *s);
 
376
}