[BACK]Return to extend.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / mg

Annotation of src/usr.bin/mg/extend.c, Revision 1.67

1.67    ! lum         1: /*     $OpenBSD: extend.c,v 1.66 2019/07/05 14:50:59 lum Exp $ */
1.34      kjell       2: /* This file is in the public domain. */
1.6       niklas      3:
1.1       deraadt     4: /*
1.65      lum         5:  *     Extended (M-x) commands, rebinding, and startup file processing.
1.1       deraadt     6:  */
1.51      kjell       7:
1.60      bcallah     8: #include <sys/queue.h>
1.51      kjell       9: #include <sys/types.h>
1.67    ! lum        10: #include <regex.h>
1.51      kjell      11: #include <ctype.h>
1.57      guenther   12: #include <limits.h>
1.60      bcallah    13: #include <signal.h>
                     14: #include <stdio.h>
                     15: #include <stdlib.h>
                     16: #include <string.h>
1.39      kjell      17:
1.60      bcallah    18: #include "chrdef.h"
                     19: #include "def.h"
                     20: #include "funmap.h"
                     21: #include "kbd.h"
                     22: #include "key.h"
1.5       millert    23: #include "macro.h"
1.1       deraadt    24:
1.21      millert    25: static int      remap(KEYMAP *, int, PF, KEYMAP *);
1.29      vincent    26: static KEYMAP  *reallocmap(KEYMAP *);
1.21      millert    27: static void     fixmap(KEYMAP *, KEYMAP *, KEYMAP *);
1.23      vincent    28: static int      dobind(KEYMAP *, const char *, int);
1.21      millert    29: static char    *skipwhite(char *);
                     30: static char    *parsetoken(char *);
1.23      vincent    31: static int      bindkey(KEYMAP **, const char *, KCHAR *, int);
1.1       deraadt    32:
1.15      mickey     33: /*
1.33      db         34:  * Insert a string, mainly for use from macros (created by selfinsert).
1.5       millert    35:  */
1.4       millert    36: /* ARGSUSED */
                     37: int
1.23      vincent    38: insert(int f, int n)
1.1       deraadt    39: {
1.31      vincent    40:        char     buf[128], *bufp, *cp;
1.5       millert    41:        int      count, c;
1.1       deraadt    42:
1.4       millert    43:        if (inmacro) {
                     44:                while (--n >= 0) {
                     45:                        for (count = 0; count < maclcur->l_used; count++) {
                     46:                                if ((((c = maclcur->l_text[count]) == '\n')
                     47:                                    ? lnewline() : linsert(1, c)) != TRUE)
1.33      db         48:                                        return (FALSE);
1.4       millert    49:                        }
                     50:                }
                     51:                maclcur = maclcur->l_fp;
1.33      db         52:                return (TRUE);
1.1       deraadt    53:        }
1.4       millert    54:        if (n == 1)
1.5       millert    55:                /* CFINS means selfinsert can tack on the end */
                     56:                thisflag |= CFINS;
1.52      lum        57:
1.31      vincent    58:        if ((bufp = eread("Insert: ", buf, sizeof(buf), EFNEW)) == NULL)
1.33      db         59:                return (ABORT);
1.31      vincent    60:        else if (bufp[0] == '\0')
1.33      db         61:                return (FALSE);
1.4       millert    62:        while (--n >= 0) {
                     63:                cp = buf;
                     64:                while (*cp) {
                     65:                        if (((*cp == '\n') ? lnewline() : linsert(1, *cp))
                     66:                            != TRUE)
1.33      db         67:                                return (FALSE);
1.4       millert    68:                        cp++;
                     69:                }
1.1       deraadt    70:        }
1.33      db         71:        return (TRUE);
1.1       deraadt    72: }
                     73:
                     74: /*
                     75:  * Bind a key to a function.  Cases range from the trivial (replacing an
1.33      db         76:  * existing binding) to the extremely complex (creating a new prefix in a
1.1       deraadt    77:  * map_element that already has one, so the map_element must be split,
                     78:  * but the keymap doesn't have enough room for another map_element, so
                     79:  * the keymap is reallocated). No attempt is made to reclaim space no
                     80:  * longer used, if this is a problem flags must be added to indicate
1.50      martin     81:  * malloced versus static storage in both keymaps and map_elements.
1.1       deraadt    82:  * Structure assignments would come in real handy, but K&R based compilers
                     83:  * don't have them.  Care is taken so running out of memory will leave
                     84:  * the keymap in a usable state.
1.49      kjell      85:  * Parameters are:
                     86:  * curmap:     pointer to the map being changed
                     87:  * c:          character being changed
                     88:  * funct:      function being changed to
                     89:  * pref_map:   if funct==NULL, map to bind to or NULL for new
1.1       deraadt    90:  */
1.4       millert    91: static int
1.49      kjell      92: remap(KEYMAP *curmap, int c, PF funct, KEYMAP *pref_map)
1.1       deraadt    93: {
1.5       millert    94:        int              i, n1, n2, nold;
1.30      vincent    95:        KEYMAP          *mp, *newmap;
1.5       millert    96:        PF              *pfp;
1.40      deraadt    97:        struct map_element      *mep;
1.4       millert    98:
                     99:        if (ele >= &curmap->map_element[curmap->map_num] || c < ele->k_base) {
1.7       art       100:                if (ele > &curmap->map_element[0] && (funct != NULL ||
1.5       millert   101:                    (ele - 1)->k_prefmap == NULL))
1.4       millert   102:                        n1 = c - (ele - 1)->k_num;
1.5       millert   103:                else
1.4       millert   104:                        n1 = HUGE;
                    105:                if (ele < &curmap->map_element[curmap->map_num] &&
1.7       art       106:                    (funct != NULL || ele->k_prefmap == NULL))
1.4       millert   107:                        n2 = ele->k_base - c;
1.5       millert   108:                else
1.4       millert   109:                        n2 = HUGE;
                    110:                if (n1 <= MAPELEDEF && n1 <= n2) {
                    111:                        ele--;
1.45      kjell     112:                        if ((pfp = calloc(c - ele->k_base + 1,
1.4       millert   113:                            sizeof(PF))) == NULL) {
1.54      lum       114:                                dobeep();
1.4       millert   115:                                ewprintf("Out of memory");
1.33      db        116:                                return (FALSE);
1.4       millert   117:                        }
                    118:                        nold = ele->k_num - ele->k_base + 1;
                    119:                        for (i = 0; i < nold; i++)
                    120:                                pfp[i] = ele->k_funcp[i];
                    121:                        while (--n1)
                    122:                                pfp[i++] = curmap->map_default;
                    123:                        pfp[i] = funct;
                    124:                        ele->k_num = c;
                    125:                        ele->k_funcp = pfp;
                    126:                } else if (n2 <= MAPELEDEF) {
1.45      kjell     127:                        if ((pfp = calloc(ele->k_num - c + 1,
1.5       millert   128:                            sizeof(PF))) == NULL) {
1.54      lum       129:                                dobeep();
1.4       millert   130:                                ewprintf("Out of memory");
1.33      db        131:                                return (FALSE);
1.4       millert   132:                        }
                    133:                        nold = ele->k_num - ele->k_base + 1;
                    134:                        for (i = 0; i < nold; i++)
                    135:                                pfp[i + n2] = ele->k_funcp[i];
                    136:                        while (--n2)
                    137:                                pfp[n2] = curmap->map_default;
                    138:                        pfp[0] = funct;
                    139:                        ele->k_base = c;
                    140:                        ele->k_funcp = pfp;
1.1       deraadt   141:                } else {
1.30      vincent   142:                        if (curmap->map_num >= curmap->map_max) {
                    143:                                if ((newmap = reallocmap(curmap)) == NULL)
1.33      db        144:                                        return (FALSE);
1.30      vincent   145:                                curmap = newmap;
                    146:                        }
1.13      art       147:                        if ((pfp = malloc(sizeof(PF))) == NULL) {
1.54      lum       148:                                dobeep();
1.4       millert   149:                                ewprintf("Out of memory");
1.33      db        150:                                return (FALSE);
1.4       millert   151:                        }
                    152:                        pfp[0] = funct;
                    153:                        for (mep = &curmap->map_element[curmap->map_num];
                    154:                            mep > ele; mep--) {
                    155:                                mep->k_base = (mep - 1)->k_base;
                    156:                                mep->k_num = (mep - 1)->k_num;
                    157:                                mep->k_funcp = (mep - 1)->k_funcp;
                    158:                                mep->k_prefmap = (mep - 1)->k_prefmap;
                    159:                        }
                    160:                        ele->k_base = c;
                    161:                        ele->k_num = c;
                    162:                        ele->k_funcp = pfp;
                    163:                        ele->k_prefmap = NULL;
                    164:                        curmap->map_num++;
                    165:                }
1.7       art       166:                if (funct == NULL) {
1.29      vincent   167:                        if (pref_map != NULL)
1.4       millert   168:                                ele->k_prefmap = pref_map;
1.29      vincent   169:                        else {
1.45      kjell     170:                                if ((mp = malloc(sizeof(KEYMAP) +
1.40      deraadt   171:                                    (MAPINIT - 1) * sizeof(struct map_element))) == NULL) {
1.54      lum       172:                                        dobeep();
1.4       millert   173:                                        ewprintf("Out of memory");
                    174:                                        ele->k_funcp[c - ele->k_base] =
                    175:                                            curmap->map_default;
1.33      db        176:                                        return (FALSE);
1.4       millert   177:                                }
                    178:                                mp->map_num = 0;
                    179:                                mp->map_max = MAPINIT;
                    180:                                mp->map_default = rescan;
                    181:                                ele->k_prefmap = mp;
                    182:                        }
1.1       deraadt   183:                }
                    184:        } else {
1.4       millert   185:                n1 = c - ele->k_base;
1.7       art       186:                if (ele->k_funcp[n1] == funct && (funct != NULL ||
1.4       millert   187:                    pref_map == NULL || pref_map == ele->k_prefmap))
1.5       millert   188:                        /* no change */
1.33      db        189:                        return (TRUE);
1.7       art       190:                if (funct != NULL || ele->k_prefmap == NULL) {
                    191:                        if (ele->k_funcp[n1] == NULL)
1.13      art       192:                                ele->k_prefmap = NULL;
1.5       millert   193:                        /* easy case */
                    194:                        ele->k_funcp[n1] = funct;
1.7       art       195:                        if (funct == NULL) {
1.4       millert   196:                                if (pref_map != NULL)
                    197:                                        ele->k_prefmap = pref_map;
                    198:                                else {
1.28      vincent   199:                                        if ((mp = malloc(sizeof(KEYMAP) +
1.15      mickey    200:                                            (MAPINIT - 1) *
1.40      deraadt   201:                                            sizeof(struct map_element))) == NULL) {
1.54      lum       202:                                                dobeep();
1.4       millert   203:                                                ewprintf("Out of memory");
                    204:                                                ele->k_funcp[c - ele->k_base] =
                    205:                                                    curmap->map_default;
1.33      db        206:                                                return (FALSE);
1.4       millert   207:                                        }
                    208:                                        mp->map_num = 0;
                    209:                                        mp->map_max = MAPINIT;
                    210:                                        mp->map_default = rescan;
                    211:                                        ele->k_prefmap = mp;
                    212:                                }
                    213:                        }
                    214:                } else {
                    215:                        /*
1.5       millert   216:                         * This case is the splits.
                    217:                         * Determine which side of the break c goes on
1.4       millert   218:                         * 0 = after break; 1 = before break
                    219:                         */
                    220:                        n2 = 1;
                    221:                        for (i = 0; n2 && i < n1; i++)
1.7       art       222:                                n2 &= ele->k_funcp[i] != NULL;
1.49      kjell     223:                        if (curmap->map_num >= curmap->map_max) {
                    224:                                if ((newmap = reallocmap(curmap)) == NULL)
                    225:                                        return (FALSE);
                    226:                                curmap = newmap;
                    227:                        }
1.45      kjell     228:                        if ((pfp = calloc(ele->k_num - c + !n2,
1.5       millert   229:                            sizeof(PF))) == NULL) {
1.54      lum       230:                                dobeep();
1.4       millert   231:                                ewprintf("Out of memory");
1.33      db        232:                                return (FALSE);
1.4       millert   233:                        }
1.7       art       234:                        ele->k_funcp[n1] = NULL;
1.4       millert   235:                        for (i = n1 + n2; i <= ele->k_num - ele->k_base; i++)
                    236:                                pfp[i - n1 - n2] = ele->k_funcp[i];
                    237:                        for (mep = &curmap->map_element[curmap->map_num];
                    238:                            mep > ele; mep--) {
                    239:                                mep->k_base = (mep - 1)->k_base;
                    240:                                mep->k_num = (mep - 1)->k_num;
                    241:                                mep->k_funcp = (mep - 1)->k_funcp;
                    242:                                mep->k_prefmap = (mep - 1)->k_prefmap;
                    243:                        }
                    244:                        ele->k_num = c - !n2;
                    245:                        (ele + 1)->k_base = c + n2;
                    246:                        (ele + 1)->k_funcp = pfp;
                    247:                        ele += !n2;
                    248:                        ele->k_prefmap = NULL;
                    249:                        curmap->map_num++;
                    250:                        if (pref_map == NULL) {
                    251:                                if ((mp = malloc(sizeof(KEYMAP) + (MAPINIT - 1)
1.40      deraadt   252:                                    * sizeof(struct map_element))) == NULL) {
1.54      lum       253:                                        dobeep();
1.4       millert   254:                                        ewprintf("Out of memory");
                    255:                                        ele->k_funcp[c - ele->k_base] =
                    256:                                            curmap->map_default;
1.33      db        257:                                        return (FALSE);
1.4       millert   258:                                }
                    259:                                mp->map_num = 0;
                    260:                                mp->map_max = MAPINIT;
                    261:                                mp->map_default = rescan;
                    262:                                ele->k_prefmap = mp;
                    263:                        } else
                    264:                                ele->k_prefmap = pref_map;
                    265:                }
1.1       deraadt   266:        }
1.33      db        267:        return (TRUE);
1.1       deraadt   268: }
                    269:
1.4       millert   270: /*
1.49      kjell     271:  * Reallocate a keymap. Returns NULL (without trashing the current map)
                    272:  * on failure.
1.4       millert   273:  */
                    274: static KEYMAP *
1.29      vincent   275: reallocmap(KEYMAP *curmap)
1.4       millert   276: {
1.40      deraadt   277:        struct maps_s   *mps;
1.5       millert   278:        KEYMAP  *mp;
                    279:        int      i;
1.4       millert   280:
1.45      kjell     281:        if (curmap->map_max > SHRT_MAX - MAPGROW) {
1.54      lum       282:                dobeep();
1.45      kjell     283:                ewprintf("keymap too large");
                    284:                return (NULL);
                    285:        }
                    286:        if ((mp = malloc(sizeof(KEYMAP) + (curmap->map_max + (MAPGROW - 1)) *
                    287:            sizeof(struct map_element))) == NULL) {
1.54      lum       288:                dobeep();
1.4       millert   289:                ewprintf("Out of memory");
1.33      db        290:                return (NULL);
1.4       millert   291:        }
                    292:        mp->map_num = curmap->map_num;
                    293:        mp->map_max = curmap->map_max + MAPGROW;
                    294:        mp->map_default = curmap->map_default;
                    295:        for (i = curmap->map_num; i--;) {
                    296:                mp->map_element[i].k_base = curmap->map_element[i].k_base;
                    297:                mp->map_element[i].k_num = curmap->map_element[i].k_num;
                    298:                mp->map_element[i].k_funcp = curmap->map_element[i].k_funcp;
                    299:                mp->map_element[i].k_prefmap = curmap->map_element[i].k_prefmap;
                    300:        }
1.17      art       301:        for (mps = maps; mps != NULL; mps = mps->p_next) {
                    302:                if (mps->p_map == curmap)
                    303:                        mps->p_map = mp;
1.4       millert   304:                else
1.17      art       305:                        fixmap(curmap, mp, mps->p_map);
1.4       millert   306:        }
                    307:        ele = &mp->map_element[ele - &curmap->map_element[0]];
1.33      db        308:        return (mp);
1.4       millert   309: }
                    310:
                    311: /*
                    312:  * Fix references to a reallocated keymap (recursive).
                    313:  */
1.12      art       314: static void
1.23      vincent   315: fixmap(KEYMAP *curmap, KEYMAP *mp, KEYMAP *mt)
1.4       millert   316: {
1.5       millert   317:        int      i;
1.4       millert   318:
                    319:        for (i = mt->map_num; i--;) {
                    320:                if (mt->map_element[i].k_prefmap != NULL) {
                    321:                        if (mt->map_element[i].k_prefmap == curmap)
                    322:                                mt->map_element[i].k_prefmap = mp;
                    323:                        else
                    324:                                fixmap(curmap, mp, mt->map_element[i].k_prefmap);
                    325:                }
1.1       deraadt   326:        }
                    327: }
                    328:
                    329: /*
1.33      db        330:  * Do the input for local-set-key, global-set-key  and define-key
1.1       deraadt   331:  * then call remap to do the work.
                    332:  */
1.4       millert   333: static int
1.23      vincent   334: dobind(KEYMAP *curmap, const char *p, int unbind)
1.4       millert   335: {
1.5       millert   336:        KEYMAP  *pref_map = NULL;
                    337:        PF       funct;
1.41      kjell     338:        char     bprompt[80], *bufp, *pep;
1.26      vincent   339:        int      c, s, n;
1.1       deraadt   340:
1.4       millert   341:        if (macrodef) {
                    342:                /*
                    343:                 * Keystrokes aren't collected. Not hard, but pretty useless.
                    344:                 * Would not work for function keys in any case.
                    345:                 */
1.54      lum       346:                dobeep();
1.4       millert   347:                ewprintf("Can't rebind key in macro");
1.33      db        348:                return (FALSE);
1.1       deraadt   349:        }
1.4       millert   350:        if (inmacro) {
                    351:                for (s = 0; s < maclcur->l_used - 1; s++) {
1.8       art       352:                        if (doscan(curmap, c = CHARMASK(maclcur->l_text[s]), &curmap)
1.7       art       353:                            != NULL) {
1.13      art       354:                                if (remap(curmap, c, NULL, NULL)
1.4       millert   355:                                    != TRUE)
1.33      db        356:                                        return (FALSE);
1.4       millert   357:                        }
1.1       deraadt   358:                }
1.12      art       359:                (void)doscan(curmap, c = maclcur->l_text[s], NULL);
1.4       millert   360:                maclcur = maclcur->l_fp;
1.1       deraadt   361:        } else {
1.41      kjell     362:                n = strlcpy(bprompt, p, sizeof(bprompt));
                    363:                if (n >= sizeof(bprompt))
                    364:                        n = sizeof(bprompt) - 1;
                    365:                pep = bprompt + n;
1.4       millert   366:                for (;;) {
1.41      kjell     367:                        ewprintf("%s", bprompt);
1.4       millert   368:                        pep[-1] = ' ';
1.42      kjell     369:                        pep = getkeyname(pep, sizeof(bprompt) -
1.41      kjell     370:                            (pep - bprompt), c = getkey(FALSE));
1.8       art       371:                        if (doscan(curmap, c, &curmap) != NULL)
1.4       millert   372:                                break;
                    373:                        *pep++ = '-';
                    374:                        *pep = '\0';
                    375:                }
1.1       deraadt   376:        }
1.4       millert   377:        if (unbind)
                    378:                funct = rescan;
1.1       deraadt   379:        else {
1.41      kjell     380:                if ((bufp = eread("%s to command: ", bprompt, sizeof(bprompt),
                    381:                    EFFUNC | EFNEW, bprompt)) == NULL)
1.33      db        382:                        return (ABORT);
1.31      vincent   383:                else if (bufp[0] == '\0')
1.33      db        384:                        return (FALSE);
1.41      kjell     385:                if (((funct = name_function(bprompt)) == NULL) ?
                    386:                    (pref_map = name_map(bprompt)) == NULL : funct == NULL) {
1.54      lum       387:                        dobeep();
1.4       millert   388:                        ewprintf("[No match]");
1.33      db        389:                        return (FALSE);
1.4       millert   390:                }
1.1       deraadt   391:        }
1.33      db        392:        return (remap(curmap, c, funct, pref_map));
1.1       deraadt   393: }
                    394:
                    395: /*
1.15      mickey    396:  * bindkey: bind key sequence to a function in the specified map.  Used by
                    397:  * excline so it can bind function keys.  To close to release to change
                    398:  * calling sequence, should just pass KEYMAP *curmap rather than
1.5       millert   399:  * KEYMAP **mapp.
                    400:  */
                    401: static int
1.23      vincent   402: bindkey(KEYMAP **mapp, const char *fname, KCHAR *keys, int kcount)
1.5       millert   403: {
                    404:        KEYMAP  *curmap = *mapp;
                    405:        KEYMAP  *pref_map = NULL;
                    406:        PF       funct;
                    407:        int      c;
1.1       deraadt   408:
1.4       millert   409:        if (fname == NULL)
                    410:                funct = rescan;
1.7       art       411:        else if (((funct = name_function(fname)) == NULL) ?
1.5       millert   412:            (pref_map = name_map(fname)) == NULL : funct == NULL) {
1.54      lum       413:                dobeep();
1.4       millert   414:                ewprintf("[No match: %s]", fname);
1.33      db        415:                return (FALSE);
1.4       millert   416:        }
                    417:        while (--kcount) {
1.8       art       418:                if (doscan(curmap, c = *keys++, &curmap) != NULL) {
1.13      art       419:                        if (remap(curmap, c, NULL, NULL) != TRUE)
1.33      db        420:                                return (FALSE);
1.9       art       421:                        /*
                    422:                         * XXX - Bizzarreness. remap creates an empty KEYMAP
                    423:                         *       that the last key is supposed to point to.
                    424:                         */
                    425:                        curmap = ele->k_prefmap;
1.4       millert   426:                }
1.1       deraadt   427:        }
1.12      art       428:        (void)doscan(curmap, c = *keys, NULL);
1.33      db        429:        return (remap(curmap, c, funct, pref_map));
1.1       deraadt   430: }
1.3       millert   431:
                    432: /*
                    433:  * Wrapper for bindkey() that converts escapes.
                    434:  */
                    435: int
1.23      vincent   436: dobindkey(KEYMAP *map, const char *func, const char *str)
1.3       millert   437: {
1.5       millert   438:        int      i;
1.3       millert   439:
                    440:        for (i = 0; *str && i < MAXKEY; i++) {
                    441:                /* XXX - convert numbers w/ strol()? */
1.38      kjell     442:                if (*str == '^' && *(str + 1) !=  '\0') {
1.56      guenther  443:                        key.k_chars[i] = CCHR(toupper((unsigned char)*++str));
1.38      kjell     444:                } else if (*str == '\\' && *(str + 1) != '\0') {
1.4       millert   445:                        switch (*++str) {
1.38      kjell     446:                        case '^':
                    447:                                key.k_chars[i] = '^';
                    448:                                break;
1.4       millert   449:                        case 't':
                    450:                        case 'T':
1.3       millert   451:                                key.k_chars[i] = '\t';
                    452:                                break;
1.4       millert   453:                        case 'n':
                    454:                        case 'N':
1.3       millert   455:                                key.k_chars[i] = '\n';
                    456:                                break;
1.4       millert   457:                        case 'r':
                    458:                        case 'R':
1.3       millert   459:                                key.k_chars[i] = '\r';
                    460:                                break;
1.4       millert   461:                        case 'e':
                    462:                        case 'E':
1.3       millert   463:                                key.k_chars[i] = CCHR('[');
                    464:                                break;
1.38      kjell     465:                        case '\\':
                    466:                                key.k_chars[i] = '\\';
                    467:                                break;
1.3       millert   468:                        }
1.38      kjell     469:                } else
                    470:                        key.k_chars[i] = *str;
1.3       millert   471:                str++;
                    472:        }
                    473:        key.k_count = i;
1.4       millert   474:        return (bindkey(&map, func, key.k_chars, key.k_count));
1.3       millert   475: }
1.1       deraadt   476:
                    477: /*
                    478:  * This function modifies the fundamental keyboard map.
                    479:  */
1.4       millert   480: /* ARGSUSED */
                    481: int
1.23      vincent   482: bindtokey(int f, int n)
1.1       deraadt   483: {
1.33      db        484:        return (dobind(fundamental_map, "Global set key: ", FALSE));
1.1       deraadt   485: }
                    486:
                    487: /*
                    488:  * This function modifies the current mode's keyboard map.
                    489:  */
1.4       millert   490: /* ARGSUSED */
                    491: int
1.23      vincent   492: localbind(int f, int n)
1.1       deraadt   493: {
1.33      db        494:        return (dobind(curbp->b_modes[curbp->b_nmodes]->p_map,
                    495:            "Local set key: ", FALSE));
1.1       deraadt   496: }
                    497:
                    498: /*
                    499:  * This function redefines a key in any keymap.
                    500:  */
1.4       millert   501: /* ARGSUSED */
                    502: int
1.42      kjell     503: redefine_key(int f, int n)
1.1       deraadt   504: {
1.33      db        505:        static char      buf[48];
                    506:        char             tmp[32], *bufp;
                    507:        KEYMAP          *mp;
                    508:
1.43      kjell     509:        (void)strlcpy(buf, "Define key map: ", sizeof(buf));
1.63      guenther  510:        if ((bufp = eread("%s", tmp, sizeof(tmp), EFNEW, buf)) == NULL)
1.33      db        511:                return (ABORT);
1.31      vincent   512:        else if (bufp[0] == '\0')
1.33      db        513:                return (FALSE);
1.35      kjell     514:        (void)strlcat(buf, tmp, sizeof(buf));
1.19      vincent   515:        if ((mp = name_map(tmp)) == NULL) {
1.54      lum       516:                dobeep();
1.19      vincent   517:                ewprintf("Unknown map %s", tmp);
1.33      db        518:                return (FALSE);
1.4       millert   519:        }
1.43      kjell     520:        if (strlcat(buf, "key: ", sizeof(buf)) >= sizeof(buf))
                    521:                return (FALSE);
1.19      vincent   522:
1.33      db        523:        return (dobind(mp, buf, FALSE));
1.1       deraadt   524: }
                    525:
1.37      kjell     526: /* ARGSUSED */
1.4       millert   527: int
1.23      vincent   528: unbindtokey(int f, int n)
1.1       deraadt   529: {
1.33      db        530:        return (dobind(fundamental_map, "Global unset key: ", TRUE));
1.1       deraadt   531: }
                    532:
1.37      kjell     533: /* ARGSUSED */
1.4       millert   534: int
1.27      vincent   535: localunbind(int f, int n)
1.1       deraadt   536: {
1.33      db        537:        return (dobind(curbp->b_modes[curbp->b_nmodes]->p_map,
                    538:            "Local unset key: ", TRUE));
1.1       deraadt   539: }
                    540:
                    541: /*
1.15      mickey    542:  * Extended command. Call the message line routine to read in the command
                    543:  * name and apply autocompletion to it. When it comes back, look the name
                    544:  * up in the symbol table and run the command if it is found.  Print an
1.5       millert   545:  * error if there is anything wrong.
1.1       deraadt   546:  */
1.4       millert   547: int
1.23      vincent   548: extend(int f, int n)
1.1       deraadt   549: {
1.5       millert   550:        PF       funct;
1.31      vincent   551:        char     xname[NXNAME], *bufp;
1.4       millert   552:
                    553:        if (!(f & FFARG))
1.31      vincent   554:                bufp = eread("M-x ", xname, NXNAME, EFNEW | EFFUNC);
1.4       millert   555:        else
1.31      vincent   556:                bufp = eread("%d M-x ", xname, NXNAME, EFNEW | EFFUNC, n);
                    557:        if (bufp == NULL)
1.33      db        558:                return (ABORT);
1.31      vincent   559:        else if (bufp[0] == '\0')
1.33      db        560:                return (FALSE);
1.31      vincent   561:        if ((funct = name_function(bufp)) != NULL) {
1.4       millert   562:                if (macrodef) {
1.40      deraadt   563:                        struct line     *lp = maclcur;
1.4       millert   564:                        macro[macrocount - 1].m_funct = funct;
                    565:                        maclcur = lp->l_bp;
                    566:                        maclcur->l_fp = lp->l_fp;
1.44      kjell     567:                        free(lp);
1.4       millert   568:                }
1.33      db        569:                return ((*funct)(f, n));
1.1       deraadt   570:        }
1.54      lum       571:        dobeep();
1.1       deraadt   572:        ewprintf("[No match]");
1.33      db        573:        return (FALSE);
1.1       deraadt   574: }
                    575:
                    576: /*
                    577:  * Define the commands needed to do startup-file processing.
                    578:  * This code is mostly a kludge just so we can get startup-file processing.
                    579:  *
                    580:  * If you're serious about having this code, you should rewrite it.
                    581:  * To wit:
                    582:  *     It has lots of funny things in it to make the startup-file look
                    583:  *     like a GNU startup file; mostly dealing with parens and semicolons.
                    584:  *     This should all vanish.
                    585:  *
                    586:  * We define eval-expression because it's easy.         It can make
                    587:  * *-set-key or define-key set an arbitrary key sequence, so it isn't
                    588:  * useless.
                    589:  */
                    590:
                    591: /*
                    592:  * evalexpr - get one line from the user, and run it.
                    593:  */
1.4       millert   594: /* ARGSUSED */
                    595: int
1.23      vincent   596: evalexpr(int f, int n)
1.1       deraadt   597: {
1.31      vincent   598:        char     exbuf[128], *bufp;
1.1       deraadt   599:
1.35      kjell     600:        if ((bufp = eread("Eval: ", exbuf, sizeof(exbuf),
                    601:            EFNEW | EFCR)) == NULL)
1.33      db        602:                return (ABORT);
1.31      vincent   603:        else if (bufp[0] == '\0')
1.33      db        604:                return (FALSE);
                    605:        return (excline(exbuf));
1.1       deraadt   606: }
1.4       millert   607:
1.1       deraadt   608: /*
1.15      mickey    609:  * evalbuffer - evaluate the current buffer as line commands. Useful for
1.5       millert   610:  * testing startup files.
1.1       deraadt   611:  */
1.4       millert   612: /* ARGSUSED */
                    613: int
1.23      vincent   614: evalbuffer(int f, int n)
1.1       deraadt   615: {
1.40      deraadt   616:        struct line             *lp;
                    617:        struct buffer           *bp = curbp;
1.5       millert   618:        int              s;
                    619:        static char      excbuf[128];
1.1       deraadt   620:
1.48      kjell     621:        for (lp = bfirstlp(bp); lp != bp->b_headp; lp = lforw(lp)) {
1.4       millert   622:                if (llength(lp) >= 128)
1.33      db        623:                        return (FALSE);
1.12      art       624:                (void)strncpy(excbuf, ltext(lp), llength(lp));
1.5       millert   625:
                    626:                /* make sure it's terminated */
                    627:                excbuf[llength(lp)] = '\0';
1.4       millert   628:                if ((s = excline(excbuf)) != TRUE)
1.33      db        629:                        return (s);
1.1       deraadt   630:        }
1.33      db        631:        return (TRUE);
1.1       deraadt   632: }
1.4       millert   633:
1.1       deraadt   634: /*
                    635:  * evalfile - go get a file and evaluate it as line commands. You can
                    636:  *     go get your own startup file if need be.
                    637:  */
1.4       millert   638: /* ARGSUSED */
                    639: int
1.23      vincent   640: evalfile(int f, int n)
1.1       deraadt   641: {
1.31      vincent   642:        char     fname[NFILEN], *bufp;
1.1       deraadt   643:
1.35      kjell     644:        if ((bufp = eread("Load file: ", fname, NFILEN,
                    645:            EFNEW | EFCR)) == NULL)
1.33      db        646:                return (ABORT);
1.31      vincent   647:        else if (bufp[0] == '\0')
1.33      db        648:                return (FALSE);
                    649:        return (load(fname));
1.1       deraadt   650: }
                    651:
                    652: /*
                    653:  * load - go load the file name we got passed.
                    654:  */
1.4       millert   655: int
1.23      vincent   656: load(const char *fname)
1.4       millert   657: {
1.64      lum       658:        int      s = TRUE, line, ret;
1.18      matthieu  659:        int      nbytes = 0;
1.66      lum       660:        char     excbuf[128], fncpy[NFILEN];
1.53      lum       661:        FILE    *ffp;
1.1       deraadt   662:
1.46      jason     663:        if ((fname = adjustname(fname, TRUE)) == NULL)
1.5       millert   664:                /* just to be careful */
1.33      db        665:                return (FALSE);
1.1       deraadt   666:
1.64      lum       667:        ret = ffropen(&ffp, fname, NULL);
                    668:        if (ret != FIOSUC) {
                    669:                if (ret == FIODIR)
                    670:                        (void)ffclose(ffp, NULL);
1.33      db        671:                return (FALSE);
1.64      lum       672:        }
1.5       millert   673:
1.66      lum       674:        /* keep a note of fname incase of errors in loaded file. */
                    675:        (void)strlcpy(fncpy, fname, sizeof(fncpy));
1.25      vincent   676:        line = 0;
1.53      lum       677:        while ((s = ffgetline(ffp, excbuf, sizeof(excbuf) - 1, &nbytes))
                    678:            == FIOSUC) {
1.25      vincent   679:                line++;
1.1       deraadt   680:                excbuf[nbytes] = '\0';
                    681:                if (excline(excbuf) != TRUE) {
                    682:                        s = FIOERR;
1.54      lum       683:                        dobeep();
1.66      lum       684:                        ewprintf("Error loading file %s at line %d", fncpy, line);
1.1       deraadt   685:                        break;
                    686:                }
                    687:        }
1.53      lum       688:        (void)ffclose(ffp, NULL);
1.1       deraadt   689:        excbuf[nbytes] = '\0';
1.4       millert   690:        if (s != FIOEOF || (nbytes && excline(excbuf) != TRUE))
1.33      db        691:                return (FALSE);
                    692:        return (TRUE);
1.1       deraadt   693: }
                    694:
                    695: /*
1.67    ! lum       696:  * Line has a '(' as the first non-white char.
        !           697:  */
        !           698: static int
        !           699: multiarg(char *funstr)
        !           700: {
        !           701:        regex_t  regex_buff;
        !           702:        PF       funcp;
        !           703:        char     excbuf[128];
        !           704:        char    *cmdp, *argp, *fendp, *endp, *p, *s = " ";
        !           705:        int      singlecmd = 0, spc, numparams, numspc;
        !           706:
        !           707:        endp = strrchr(funstr, ')');
        !           708:        if (endp == NULL) {
        !           709:                ewprintf("No closing parenthesis found");
        !           710:                return(FALSE);
        !           711:        }
        !           712:        p = endp + 1;
        !           713:        if (*p != '\0')
        !           714:                *p = '\0';
        !           715:        /* we now know that string starts with '(' and ends with ')' */
        !           716:        if (regcomp(&regex_buff, "^[(][\t ]*[)]$", REG_EXTENDED)) {
        !           717:                dobeep();
        !           718:                ewprintf("Could not compile regex");
        !           719:                regfree(&regex_buff);
        !           720:                return(FALSE);
        !           721:        }
        !           722:        if (!regexec(&regex_buff, funstr, 0, NULL, 0)) {
        !           723:                dobeep();
        !           724:                ewprintf("No command found");
        !           725:                regfree(&regex_buff);
        !           726:                return(FALSE);
        !           727:        }
        !           728:        /* currently there are no mg commands that don't have a letter */
        !           729:        if (regcomp(&regex_buff, "^[(][\t ]*[A-Za-z-]+[\t ]*[)]$",
        !           730:            REG_EXTENDED)) {
        !           731:                dobeep();
        !           732:                ewprintf("Could not compile regex");
        !           733:                regfree(&regex_buff);
        !           734:                return(FALSE);
        !           735:        }
        !           736:        if (!regexec(&regex_buff, funstr, 0, NULL, 0))
        !           737:                singlecmd = 1;
        !           738:
        !           739:        regfree(&regex_buff);
        !           740:        p = funstr + 1;         /* move past first '(' char.    */
        !           741:        cmdp = skipwhite(p);    /* find first char of command.  */
        !           742:
        !           743:        if (singlecmd) {
        !           744:                /* remove ')', then check for spaces at the end */
        !           745:                cmdp[strlen(cmdp) - 1] = '\0';
        !           746:                if ((fendp = strchr(cmdp, ' ')) != NULL)
        !           747:                        *fendp = '\0';
        !           748:                else if ((fendp = strchr(cmdp, '\t')) != NULL)
        !           749:                        *fendp = '\0';
        !           750:                return(excline(cmdp));
        !           751:        }
        !           752:        if ((fendp = strchr(cmdp, ' ')) == NULL)
        !           753:                fendp = strchr(cmdp, '\t');
        !           754:
        !           755:        *fendp = '\0';
        !           756:        /*
        !           757:         * If no extant mg command found, line could be a (define of some kind.
        !           758:         * Since no defines exist at the moment, just return.
        !           759:         */
        !           760:        if ((funcp = name_function(cmdp)) == NULL) {
        !           761:                dobeep();
        !           762:                ewprintf("Unknown command: %s", cmdp);
        !           763:                return (FALSE);
        !           764:        }
        !           765:        numparams = numparams_function(funcp);
        !           766:        if (numparams == 0) {
        !           767:                dobeep();
        !           768:                ewprintf("Command takes no arguments: %s", cmdp);
        !           769:                return (FALSE);
        !           770:        }
        !           771:
        !           772:        /* now find the first argument */
        !           773:        p = fendp + 1;
        !           774:        argp = skipwhite(p);
        !           775:        numspc = spc = 1; /* initially fake a space so we find first argument */
        !           776:
        !           777:        for (p = argp; *p != '\0'; p++) {
        !           778:                if (*p == ' ' || *p == '\t' || *p == ')') {
        !           779:                        if (spc == 1)
        !           780:                                continue;
        !           781:                        if (spc == 0 && (numspc % numparams == 0)) {
        !           782:                                *p = '\0';      /* terminate arg string */
        !           783:                                excbuf[0] = '\0';
        !           784:                                if (strlcpy(excbuf, cmdp, sizeof(excbuf))
        !           785:                                     >= sizeof(excbuf)) {
        !           786:                                        dobeep();
        !           787:                                        ewprintf("strlcpy error");
        !           788:                                        return (FALSE);
        !           789:                                }
        !           790:                                if (strlcat(excbuf, s, sizeof(excbuf))
        !           791:                                    >= sizeof(excbuf)) {
        !           792:                                        dobeep();
        !           793:                                        ewprintf("strlcpy error");
        !           794:                                        return (FALSE);
        !           795:                                }
        !           796:                                if (strlcat(excbuf, argp, sizeof(excbuf))
        !           797:                                    >= sizeof(excbuf)) {
        !           798:                                        dobeep();
        !           799:                                        ewprintf("strlcpy error");
        !           800:                                        return (FALSE);
        !           801:                                }
        !           802:                                excline(excbuf);
        !           803:                                *p = ' ';       /* so 'for' loop can continue */
        !           804:                        }
        !           805:                        numspc++;
        !           806:                        spc = 1;
        !           807:                } else {
        !           808:                        if (spc == 1)
        !           809:                                if ((numparams == 1) ||
        !           810:                                    ((numspc + 1) % numparams) == 0)
        !           811:                                        argp = p;
        !           812:                        spc = 0;
        !           813:                }
        !           814:        }
        !           815:        return (TRUE);
        !           816: }
        !           817:
        !           818: /*
1.59      bcallah   819:  * excline - run a line from a load file or eval-expression.
1.1       deraadt   820:  */
1.4       millert   821: int
1.23      vincent   822: excline(char *line)
1.1       deraadt   823: {
1.5       millert   824:        PF       fp;
1.40      deraadt   825:        struct line     *lp, *np;
1.5       millert   826:        int      status, c, f, n;
1.22      ho        827:        char    *funcp, *tmp;
1.5       millert   828:        char    *argp = NULL;
1.22      ho        829:        long     nl;
1.5       millert   830:        int      bind;
                    831:        KEYMAP  *curmap;
                    832: #define BINDARG                0  /* this arg is key to bind (local/global set key) */
                    833: #define        BINDNO          1  /* not binding or non-quoted BINDARG */
                    834: #define BINDNEXT       2  /* next arg " (define-key) */
                    835: #define BINDDO         3  /* already found key to bind */
                    836: #define BINDEXT                1  /* space for trailing \0 */
                    837:
                    838:        lp = NULL;
1.1       deraadt   839:
1.4       millert   840:        if (macrodef || inmacro) {
1.54      lum       841:                dobeep();
1.1       deraadt   842:                ewprintf("Not now!");
1.33      db        843:                return (FALSE);
1.1       deraadt   844:        }
                    845:        f = 0;
                    846:        n = 1;
                    847:        funcp = skipwhite(line);
1.4       millert   848:        if (*funcp == '\0')
1.33      db        849:                return (TRUE);  /* No error on blank lines */
1.67    ! lum       850:        if (*funcp == '(')
        !           851:                return (multiarg(funcp));
1.1       deraadt   852:        line = parsetoken(funcp);
                    853:        if (*line != '\0') {
                    854:                *line++ = '\0';
                    855:                line = skipwhite(line);
1.20      vincent   856:                if (ISDIGIT(*line) || *line == '-') {
1.1       deraadt   857:                        argp = line;
                    858:                        line = parsetoken(line);
                    859:                }
                    860:        }
                    861:        if (argp != NULL) {
                    862:                f = FFARG;
1.22      ho        863:                nl = strtol(argp, &tmp, 10);
1.20      vincent   864:                if (*tmp != '\0')
1.33      db        865:                        return (FALSE);
1.22      ho        866:                if (nl >= INT_MAX || nl <= INT_MIN)
1.33      db        867:                        return (FALSE);
1.22      ho        868:                n = (int)nl;
1.1       deraadt   869:        }
1.4       millert   870:        if ((fp = name_function(funcp)) == NULL) {
1.54      lum       871:                dobeep();
1.4       millert   872:                ewprintf("Unknown function: %s", funcp);
1.33      db        873:                return (FALSE);
1.1       deraadt   874:        }
1.4       millert   875:        if (fp == bindtokey || fp == unbindtokey) {
1.1       deraadt   876:                bind = BINDARG;
1.11      art       877:                curmap = fundamental_map;
1.4       millert   878:        } else if (fp == localbind || fp == localunbind) {
1.1       deraadt   879:                bind = BINDARG;
                    880:                curmap = curbp->b_modes[curbp->b_nmodes]->p_map;
1.42      kjell     881:        } else if (fp == redefine_key)
1.4       millert   882:                bind = BINDNEXT;
                    883:        else
                    884:                bind = BINDNO;
1.5       millert   885:        /* Pack away all the args now... */
1.4       millert   886:        if ((np = lalloc(0)) == FALSE)
1.33      db        887:                return (FALSE);
1.1       deraadt   888:        np->l_fp = np->l_bp = maclcur = np;
                    889:        while (*line != '\0') {
                    890:                argp = skipwhite(line);
1.4       millert   891:                if (*argp == '\0')
                    892:                        break;
1.1       deraadt   893:                line = parsetoken(argp);
                    894:                if (*argp != '"') {
1.4       millert   895:                        if (*argp == '\'')
                    896:                                ++argp;
1.20      vincent   897:                        if ((lp = lalloc((int) (line - argp) + BINDEXT)) ==
                    898:                            NULL) {
1.4       millert   899:                                status = FALSE;
                    900:                                goto cleanup;
                    901:                        }
1.5       millert   902:                        bcopy(argp, ltext(lp), (int)(line - argp));
                    903:                        /* don't count BINDEXT */
                    904:                        lp->l_used--;
1.4       millert   905:                        if (bind == BINDARG)
                    906:                                bind = BINDNO;
1.5       millert   907:                } else {
                    908:                        /* quoted strings are special */
1.4       millert   909:                        ++argp;
                    910:                        if (bind != BINDARG) {
1.5       millert   911:                                lp = lalloc((int)(line - argp) + BINDEXT);
1.4       millert   912:                                if (lp == NULL) {
                    913:                                        status = FALSE;
                    914:                                        goto cleanup;
                    915:                                }
                    916:                                lp->l_used = 0;
1.33      db        917:                        } else
1.4       millert   918:                                key.k_count = 0;
                    919:                        while (*argp != '"' && *argp != '\0') {
                    920:                                if (*argp != '\\')
                    921:                                        c = *argp++;
                    922:                                else {
                    923:                                        switch (*++argp) {
                    924:                                        case 't':
                    925:                                        case 'T':
                    926:                                                c = CCHR('I');
                    927:                                                break;
                    928:                                        case 'n':
                    929:                                        case 'N':
                    930:                                                c = CCHR('J');
                    931:                                                break;
                    932:                                        case 'r':
                    933:                                        case 'R':
                    934:                                                c = CCHR('M');
                    935:                                                break;
                    936:                                        case 'e':
                    937:                                        case 'E':
                    938:                                                c = CCHR('[');
                    939:                                                break;
                    940:                                        case '^':
                    941:                                                /*
                    942:                                                 * split into two statements
                    943:                                                 * due to bug in OSK cpp
                    944:                                                 */
                    945:                                                c = CHARMASK(*++argp);
                    946:                                                c = ISLOWER(c) ?
                    947:                                                    CCHR(TOUPPER(c)) : CCHR(c);
                    948:                                                break;
                    949:                                        case '0':
                    950:                                        case '1':
                    951:                                        case '2':
                    952:                                        case '3':
                    953:                                        case '4':
                    954:                                        case '5':
                    955:                                        case '6':
                    956:                                        case '7':
                    957:                                                c = *argp - '0';
1.15      mickey    958:                                                if (argp[1] <= '7' &&
1.5       millert   959:                                                    argp[1] >= '0') {
1.4       millert   960:                                                        c <<= 3;
                    961:                                                        c += *++argp - '0';
                    962:                                                        if (argp[1] <= '7' &&
                    963:                                                            argp[1] >= '0') {
                    964:                                                                c <<= 3;
                    965:                                                                c += *++argp
                    966:                                                                    - '0';
                    967:                                                        }
                    968:                                                }
                    969:                                                break;
                    970:                                        case 'f':
                    971:                                        case 'F':
                    972:                                                c = *++argp - '0';
                    973:                                                if (ISDIGIT(argp[1])) {
                    974:                                                        c *= 10;
                    975:                                                        c += *++argp - '0';
                    976:                                                }
                    977:                                                c += KFIRST;
                    978:                                                break;
                    979:                                        default:
                    980:                                                c = CHARMASK(*argp);
                    981:                                                break;
                    982:                                        }
                    983:                                        argp++;
                    984:                                }
                    985:                                if (bind == BINDARG)
                    986:                                        key.k_chars[key.k_count++] = c;
                    987:                                else
                    988:                                        lp->l_text[lp->l_used++] = c;
                    989:                        }
                    990:                        if (*line)
                    991:                                line++;
1.1       deraadt   992:                }
1.4       millert   993:                switch (bind) {
                    994:                case BINDARG:
1.1       deraadt   995:                        bind = BINDDO;
                    996:                        break;
1.4       millert   997:                case BINDNEXT:
1.1       deraadt   998:                        lp->l_text[lp->l_used] = '\0';
1.10      art       999:                        if ((curmap = name_map(lp->l_text)) == NULL) {
1.54      lum      1000:                                dobeep();
1.4       millert  1001:                                ewprintf("No such mode: %s", lp->l_text);
                   1002:                                status = FALSE;
1.44      kjell    1003:                                free(lp);
1.4       millert  1004:                                goto cleanup;
1.1       deraadt  1005:                        }
1.44      kjell    1006:                        free(lp);
1.1       deraadt  1007:                        bind = BINDARG;
                   1008:                        break;
1.4       millert  1009:                default:
1.1       deraadt  1010:                        lp->l_fp = np->l_fp;
                   1011:                        lp->l_bp = np;
                   1012:                        np->l_fp = lp;
                   1013:                        np = lp;
                   1014:                }
                   1015:        }
1.4       millert  1016:        switch (bind) {
                   1017:        default:
1.54      lum      1018:                dobeep();
1.1       deraadt  1019:                ewprintf("Bad args to set key");
                   1020:                status = FALSE;
                   1021:                break;
1.4       millert  1022:        case BINDDO:
                   1023:                if (fp != unbindtokey && fp != localunbind) {
                   1024:                        lp->l_text[lp->l_used] = '\0';
                   1025:                        status = bindkey(&curmap, lp->l_text, key.k_chars,
                   1026:                            key.k_count);
1.33      db       1027:                } else
1.13      art      1028:                        status = bindkey(&curmap, NULL, key.k_chars,
1.4       millert  1029:                            key.k_count);
1.1       deraadt  1030:                break;
1.4       millert  1031:        case BINDNO:
1.1       deraadt  1032:                inmacro = TRUE;
                   1033:                maclcur = maclcur->l_fp;
1.5       millert  1034:                status = (*fp)(f, n);
1.1       deraadt  1035:                inmacro = FALSE;
                   1036:        }
                   1037: cleanup:
                   1038:        lp = maclcur->l_fp;
1.4       millert  1039:        while (lp != maclcur) {
                   1040:                np = lp->l_fp;
1.44      kjell    1041:                free(lp);
1.4       millert  1042:                lp = np;
1.1       deraadt  1043:        }
1.44      kjell    1044:        free(lp);
1.62      florian  1045:        maclhead = NULL;
                   1046:        macrodef = FALSE;
1.33      db       1047:        return (status);
1.1       deraadt  1048: }
                   1049:
                   1050: /*
                   1051:  * a pair of utility functions for the above
                   1052:  */
                   1053: static char *
1.23      vincent  1054: skipwhite(char *s)
1.1       deraadt  1055: {
1.67    ! lum      1056:        while (*s == ' ' || *s == '\t')
1.4       millert  1057:                s++;
1.55      lum      1058:        if ((*s == ';') || (*s == '#'))
1.4       millert  1059:                *s = '\0';
1.33      db       1060:        return (s);
1.1       deraadt  1061: }
                   1062:
                   1063: static char *
1.23      vincent  1064: parsetoken(char *s)
1.1       deraadt  1065: {
                   1066:        if (*s != '"') {
1.4       millert  1067:                while (*s && *s != ' ' && *s != '\t' && *s != ')' && *s != '(')
                   1068:                        s++;
                   1069:                if (*s == ';')
                   1070:                        *s = '\0';
1.1       deraadt  1071:        } else
1.5       millert  1072:                do {
1.15      mickey   1073:                        /*
                   1074:                         * Strings get special treatment.
                   1075:                         * Beware: You can \ out the end of the string!
1.5       millert  1076:                         */
1.4       millert  1077:                        if (*s == '\\')
                   1078:                                ++s;
                   1079:                } while (*++s != '"' && *s != '\0');
1.33      db       1080:        return (s);
1.1       deraadt  1081: }