file.c
上传用户:tianjinjs
上传日期:2007-01-05
资源大小:309k
文件大小:19k
- /*
- * file.c Functions to handle file selector.
- *
- * This file is part of the minicom communications package,
- * Copyright 1991-1995 Miquel van Smoorenburg.
- *
- * This file created from code mostly cadged from "dial.c"
- * by Miquel van Smoorenburg. Written by James S. Seymour.
- * Copyright (c) 1998 by James S. Seymour (jseymour@jimsun.LinxNet.com)
- * Some mods for i18n
- * Copyright (c) 1998 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
- #include "port.h"
- #include "minicom.h"
- #include "intl.h"
- #include "getsdir.h"
- _PROTO(extern int wildmat, (char *s, char *p));
- /* We want the ANSI offsetof macro to do some dirty stuff. */
- #ifndef offsetof
- # define offsetof(type, member) ((int) &((type *)0)->member)
- #endif
- /* Values for the "flags". */
- #define FL_ECHO 0x01 /* Local echo on/off. */
- #define FL_DEL 0x02 /* Backspace or DEL */
- #define FL_WRAP 0x04 /* Use autowrap. */
- #define FL_ANSI 0x08 /* Type of term emulation */
- #define FL_TAG 0x80 /* This entry is tagged. */
- #define FL_SAVE 0x0f /* Which portions of flags to save. */
- #define FILE_MWTR 1 /* main window top row */
- #define SUBM_OKAY 5 /* last entry in sub-menu */
- static int nrents = 1;
- _PROTO(static void file_tell, (char *s));
- /*
- * replaced by macro (on test basis)
- _PROTO(static GETSDIR_ENTRY *getno, (int no, GETSDIR_ENTRY *dirdat));
- */
- _PROTO(static void dhili, (int k));
- _PROTO(static void prdir, (WIN *dirw, int top, int cur,
- GETSDIR_ENTRY *dirdat, int longest));
- _PROTO(static void prone, (WIN *dirw, int top, int cur,
- GETSDIR_ENTRY *dirdat, int longest, int inverse));
- _PROTO(static void *set_work_dir, (void *existing, size_t min_len));
- _PROTO(static int new_filedir, (GETSDIR_ENTRY *o_dirdat, int flushit));
- _PROTO(static void goto_filedir, (char *new_dir, int absolut));
- _PROTO(static int tag_untag, (char *pat, int tag));
- _PROTO(static char *concat_list, (GETSDIR_ENTRY *d));
- _PROTO(static int init_filedir, (void));
- static WIN *dsub;
- #define WHAT_NR_OPTIONS 6
- static char *what = N_(" [Goto] [Prev] [Show] [Tag] [Untag] [Okay] ");
- /* 123456789012345678901234567890123456789012345678
- 1 2 3 4 */
- static int dprev;
- /* Little menu. */
- static char *d_yesno[] = { N_(" Yes "), N_(" No "), CNULL };
- /*
- * Tell a little message
- */
- static void
- file_tell(s)
- char *s;
- {
- WIN *w;
- w = mc_tell(s);
- sleep(1);
- wclose(w, 1);
- }
- /*
- * Highlight a choice in the horizontal menu.
- */
- static void
- dhili(k)
- int k;
- {
- int what_len = strlen (_(what)),
- what_option_len = what_len / WHAT_NR_OPTIONS,
- initial_y = (76 - (what_len >= 76 ? 74 : what_len)) / 2;
-
- if(k == dprev)
- return;
- if(dprev >= 0) {
- wlocate(dsub, initial_y + what_option_len*dprev, 0);
- if(!useattr) {
- wputs(dsub, " ");
- } else {
- wsetattr(dsub, stdattr);
- wprintf(dsub, "%*.*s", what_option_len - 1, what_option_len - 1,
- _(what) + what_option_len*dprev);
- }
- }
- dprev = k;
- wlocate(dsub, initial_y + what_option_len*k, 0);
- if(!useattr) {
- wputs(dsub, ">");
- } else {
- wsetattr(dsub, XA_REVERSE | stdattr);
- wprintf(dsub, "%*.*s", what_option_len - 1, what_option_len - 1,
- _(what) + what_option_len*k);
- wsetattr(dsub, stdattr);
- }
- }
- /*
- */
- #define getno(n,d) ((n) >= nrents? (GETSDIR_ENTRY *) NULL : &((d)[n]))
- /*
- * Get entry "no" in list.
- static GETSDIR_ENTRY *
- getno(no, dirdat)
- int no;
- GETSDIR_ENTRY *dirdat;
- {
- if(no >= nrents)
- return((GETSDIR_ENTRY *) NULL);
- return(&dirdat[no]);
- }
- */
- /*
- * Print the directory. Only draw from "cur" to bottom.
- */
- static void
- prdir(dirw, top, cur, dirdat, longest)
- WIN *dirw;
- int top, cur;
- GETSDIR_ENTRY *dirdat;
- int longest;
- {
- int f, start;
- GETSDIR_ENTRY *d;
- char f_str[BUFSIZ];
- char t_str[BUFSIZ];
- start = cur - top;
- dirflush = 0;
- sprintf(f_str, " %%-%ds", longest + 2);
- wlocate(dirw, 0, start + FILE_MWTR);
- for(f = start; f < dirw->ys - (1 + FILE_MWTR); f++) {
- if((d = getno(f + top, dirdat)) == (GETSDIR_ENTRY *) NULL)
- break;
- if(d->cflags & FL_TAG)
- wsetattr(dirw, XA_REVERSE | stdattr);
- if(S_ISDIR(d->mode)) {
- snprintf(t_str, sizeof(t_str), "[%s]", d->fname);
- wprintf(dirw, f_str, t_str);
- }
- else
- wprintf(dirw, f_str, d->fname);
- wsetattr(dirw, XA_NORMAL | stdattr);
- wputc(dirw, 'n');
- }
- dirflush = 1;
- wflush();
- }
- /*
- * Print one directory entry.
- */
- static void
- prone(dirw, top, cur, dirdat, longest, inverse)
- WIN *dirw;
- int top, cur;
- GETSDIR_ENTRY *dirdat;
- int longest;
- int inverse;
- {
- char f_str[BUFSIZ];
- char t_str[BUFSIZ];
- dirflush = 0;
- sprintf(f_str, " %%-%ds", longest + 2);
- /*
- if(dirdat->cflags & FL_TAG)
- wsetattr(dirw, XA_REVERSE | stdattr);
- */
- if(inverse)
- wsetattr(dirw, XA_REVERSE | stdattr);
- if(S_ISDIR(dirdat->mode)) {
- snprintf(t_str, sizeof(t_str), "[%s]", dirdat->fname);
- wprintf(dirw, f_str, t_str);
- }
- else
- wprintf(dirw, f_str, dirdat->fname);
- wsetattr(dirw, XA_NORMAL | stdattr);
- dirflush = 1;
- wflush();
- }
- static WIN *main_w;
- static GETSDIR_ENTRY *dirdat, *d;
- static int cur = 0;
- static int ocur = 0;
- static int subm = SUBM_OKAY;
- static int quit = 0;
- static int top = 0;
- static int c = 0;
- static int pgud = 0;
- static int first = 1;
- static char *s;
- static int longest;
- static char file_title[BUFSIZ];
- static char cwd_str[BUFSIZ];
- static char *prev_dir = NULL;
- static char *work_dir = NULL;
- static char *d_work_dir = NULL;
- static char *u_work_dir = NULL;
- static int min_len = 1;
- static char wc_str[128] = "";
- static char wc_mem[128] = "";
- static int tag_cnt = 0;
- static int how_many = 0;
- static int down_loading = 0;
- static char *ret_buf = NULL;
- static void *
- set_work_dir(existing, min_len)
- void *existing;
- size_t min_len;
- {
- void *vp;
- vp = existing == NULL? malloc(min_len) : realloc(existing, min_len);
- if(down_loading)
- d_work_dir = vp;
- else
- u_work_dir = vp;
- return(vp);
- }
- /*
- * Initialize new file directory.
- *
- * Sets the current working directory. Non-0 return = no change.
- */
- static int
- new_filedir(o_dirdat, flushit)
- GETSDIR_ENTRY *o_dirdat;
- int flushit;
- {
- static int dp_len = 0;
- static char cwd_str_fmt[BUFSIZ] = "";
- int new_dp_len,
- fmt_len;
- char disp_dir[80];
- int what_len = strlen (_(what)),
- initial_y = (76 - (what_len >= 76 ? 74 : what_len)) / 2;
- cur = 0;
- ocur = 0;
- subm = SUBM_OKAY;
- quit = 0;
- top = 0;
- c = 0;
- pgud = 0;
- first = 1;
- min_len = 1;
- dprev = -1;
- tag_cnt = 0;
- /* got to do some error-checking here!!! Maybe use mcd(), too! */
- if(prev_dir != NULL)
- free(prev_dir);
- prev_dir = getcwd(NULL, BUFSIZ);
- /*
- * get last directory
- */
- work_dir = down_loading? d_work_dir : u_work_dir;
- /*
- * init working directory to default?
- */
- if(work_dir == NULL) {
- char *s = down_loading? (P_DOWNDIR) : (P_UPDIR);
- min_len = 1;
- if(*s != '/')
- min_len += strlen(homedir) + 1;
- min_len += strlen(s);
- if(min_len < BUFSIZ)
- min_len = BUFSIZ;
- work_dir = set_work_dir(NULL, min_len);
- if(*s == '/')
- strncpy(work_dir, s, min_len);
- else
- snprintf(work_dir, min_len, "%s/%s", homedir, s);
- }
- /* lop-off trailing "/" for consistency */
- if(strlen(work_dir) > 1 && work_dir[strlen(work_dir) - 1] == '/')
- work_dir[strlen(work_dir) - 1] = (char) 0;
- chdir(work_dir);
- /* All right, draw the file directory! */
- if(flushit) {
- dirflush = 0;
- winclr(main_w);
- wredraw(main_w, 1);
- }
- wcursor(main_w, CNORMAL);
- /* select <a file|one or more files|a directory> for <upload|download> */
- snprintf(file_title, sizeof(file_title), _("Select %s for %s"),
- how_many? (how_many < 0? _("one or more files") : _("a file"))
- : _("a directory"),
- down_loading? _("download") : _("upload"));
- wtitle(main_w, TMID, file_title);
- if((new_dp_len = strlen(work_dir)) > dp_len) {
- dp_len = new_dp_len;
- snprintf(cwd_str_fmt, sizeof(cwd_str_fmt),
- _("Directory: %%-%ds"), dp_len);
- }
- if (new_dp_len + (fmt_len = strlen(cwd_str_fmt)) > 75) {
- snprintf(disp_dir, sizeof(disp_dir),
- "...%s", work_dir + new_dp_len - 73 + fmt_len);
- snprintf(cwd_str, sizeof(cwd_str), cwd_str_fmt, disp_dir);
- }
- else
- snprintf(cwd_str, sizeof(cwd_str), cwd_str_fmt, work_dir);
- wlocate(main_w, 0, 0);
- wputs(main_w, cwd_str);
- wlocate(dsub, initial_y, 0);
- wputs(dsub, _(what));
- wsetregion(main_w, 1, main_w->ys - FILE_MWTR);
- main_w->doscroll = 0;
- /* old dir to discard? */
- if(o_dirdat != (GETSDIR_ENTRY *) NULL)
- free(o_dirdat);
- /* get sorted directory */
- if((nrents = getsdir(".", wc_str,
- GETSDIR_PARNT|GETSDIR_NSORT|GETSDIR_DIRSF, 0, &dirdat, &longest)) < 0) {
- /* we really want to announce the error here!!! */
- wclose(main_w, 1);
- wclose(dsub, 1);
- free(dirdat);
- return(-1);
- }
- prdir(main_w, top, top, dirdat, longest);
- wlocate(main_w, initial_y, main_w->ys - FILE_MWTR);
- wputs(main_w, _("( Escape to exit, Space to tag )"));
- dhili(subm);
- /* this really needs to go in dhili !!!*/
- wlocate(main_w, 0, cur + FILE_MWTR - top);
- if(flushit) {
- dirflush = 1;
- wredraw(dsub, 1);
- }
- return(0);
- }
- /*
- * Goto a new directory
- */
- static void
- goto_filedir(new_dir, absolut)
- char *new_dir;
- int absolut;
- {
- if(strcmp(new_dir, "..") == 0) {
- if(strcmp(work_dir, "/")) {
- char *sp = strrchr(work_dir, '/');
- *sp = (char) 0;
- if(strlen(work_dir) == 0)
- strcpy(work_dir, "/");
- }
- else {
- file_tell(_("Can't back up!"));
- return;
- }
- }
- else if(!absolut) {
- int new_len = strlen(work_dir) + 1; /* + '/' */
- if((new_len += strlen(new_dir) + 1) > min_len) {
- min_len = new_len;
- work_dir = set_work_dir(work_dir, min_len);
- }
- if(strcmp(work_dir, "/") != 0)
- strcat(work_dir, "/");
- strcat(work_dir, new_dir);
- }
- else {
- int new_len = 1;
- if(*new_dir != '/')
- new_len += strlen(homedir) + 1;
- new_len += strlen(new_dir);
- if(min_len < new_len)
- min_len = new_len;
- work_dir = set_work_dir(work_dir, min_len);
- if(*new_dir == '/')
- strncpy(work_dir, new_dir, min_len);
- else
- snprintf(work_dir, min_len, "%s/%s", homedir, new_dir);
- }
- new_filedir(dirdat, 1);
- }
- /*
- * Initialize the file directory.
- */
- static int
- init_filedir()
- {
- int x1, x2;
- int retstat = -1;
- dirflush = 0;
- x1 = (COLS / 2) - 37;
- x2 = (COLS / 2) + 37;
- dsub = wopen(x1 - 1, LINES - 3, x2 + 1, LINES - 3, BNONE,
- stdattr, mfcolor, mbcolor, 0, 0, 1);
- main_w = wopen(x1, 2, x2, LINES - 6, BSINGLE, stdattr, mfcolor,
- mbcolor, 0, 0, 1);
- if(ret_buf != NULL ||
- (retstat = ((ret_buf = malloc(BUFSIZ)) == NULL)? -1 : 0) == 0) {
- retstat = new_filedir((GETSDIR_ENTRY *) NULL, 0);
- dirflush = 1;
- wredraw(dsub, 1);
- }
- return(retstat);
- }
- static int
- tag_untag(pat, tag)
- char *pat;
- int tag;
- {
- GETSDIR_ENTRY *my_d = dirdat;
- int indxr, cntr;
- for(indxr = nrents, cntr = 0; indxr; --indxr, ++my_d)
- if(S_ISREG(my_d->mode) && wildmat(my_d->fname, pat)) {
- if(tag) {
- my_d->cflags |= FL_TAG;
- ++cntr;
- }
- else if(my_d->cflags & FL_TAG) {
- my_d->cflags &= ~FL_TAG;
- ++cntr;
- }
- }
- return(cntr);
- }
- /*
- * concatenate tagged files into a buffer
- */
- static char *
- concat_list(d)
- GETSDIR_ENTRY *d;
- {
- GETSDIR_ENTRY *my_d;
- int indxr, len;
- my_d = d;
- for(indxr = nrents, len = 0; indxr; --indxr, ++my_d)
- if(my_d->cflags & FL_TAG)
- len += strlen(my_d->fname) + 1;
- if(len) {
- if(len > BUFSIZ) {
- if((ret_buf = realloc(ret_buf, len)) == NULL) {
- file_tell(_("Too many files tagged - buffer would overflow"));
- return(NULL);
- }
- }
-
- *ret_buf = (char) 0;
- my_d = d;
- for(indxr = nrents; indxr; --indxr, ++my_d)
- if(my_d->cflags & FL_TAG) {
- /* this could be *much* more efficient */
- strcat(ret_buf, my_d->fname);
- strcat(ret_buf, " ");
- }
- ret_buf[strlen(ret_buf) - 1] = (char) 0;
- return(ret_buf);
- }
- return(NULL);
- }
- /*
- * Draw the file directory.
- *
- * howmany - How many files can be selected
- * 0 = none (for directory selection only, as in "rz")
- * 1 = one (for single-file up-/down-loads, as in "rx")
- * -1 = any number (for multiple files, as in "sz")
- *
- * downloading - Is this for download selection?
- * 0 = no
- * 1 = yes - when single file selected, see if it exists
- */
- char *
- filedir(howmany, downloading)
- int howmany;
- int downloading;
- {
- time_t click_time = (time_t) 0;
- how_many = howmany;
- down_loading = downloading;
- init_filedir();
- again:
- wlocate(main_w, 0, cur + FILE_MWTR - top);
- if(first) {
- wredraw(main_w, 1);
- first = 0;
- }
- while(!quit) {
- d = getno(cur, dirdat);
- /*
- if(S_ISDIR(d->mode))
- prone(main_w, top, top, d, longest, 0);
- */
- switch(c = wxgetch()) {
- case K_UP:
- case 'k':
- /*
- if(S_ISDIR(d->mode))
- prone(main_w, top, top, d, longest, 1);
- */
- cur -= (cur > 0);
- break;
- case K_DN:
- case 'j':
- /*
- if(S_ISDIR(d->mode))
- prone(main_w, top, top, d, longest, 1);
- */
- cur += (cur < nrents - 1);
- break;
- case K_LT:
- case 'h':
- subm--;
- if(subm < 0)
- subm = SUBM_OKAY;
- break;
- case K_RT:
- case 'l':
- subm = (subm + 1) % 6;
- break;
- case K_PGUP:
- case ' 02': /* Control-B */
- pgud = 1;
- quit = 1;
- break;
- case K_PGDN:
- case ' 06': /* Control-F */
- pgud = 2;
- quit = 1;
- break;
- case 'f': /* Find. */
- subm = 1;
- quit = 1;
- break;
- case ' ': /* Tag if not directory */
- if(S_ISDIR(d->mode)) {
- time_t this_time = time((time_t *) NULL);
- if(this_time - click_time < 2) {
- GETSDIR_ENTRY *d2 = getno(cur, dirdat);
- goto_filedir(d2->fname, 0);
- click_time = (time_t) 0;
- }
- else
- click_time = this_time;
- }
- else {
- if(how_many) {
- if((d->cflags ^= FL_TAG) & FL_TAG) {
- if(tag_cnt && how_many == 1) {
- d->cflags &= ~FL_TAG;
- file_tell(_("Can select only one!"));
- break;
- }
- ++tag_cnt;
- }
- else
- --tag_cnt;
- wlocate(main_w, 0, cur + FILE_MWTR - top);
- prone(main_w, top, top, d, longest, d->cflags & FL_TAG);
- wputc(main_w, 'n');
- cur += (cur < nrents - 1);
- }
- }
- break;
- case 'G':
- case 'g':
- subm = 0;
- goto real_programmers_use_gotos;
- break;
- case 'P':
- case 'p':
- subm = 1;
- goto real_programmers_use_gotos;
- break;
- case 'S':
- case 's':
- subm = 2;
- goto real_programmers_use_gotos;
- break;
- case 'T':
- case 't':
- subm = 3;
- goto real_programmers_use_gotos;
- break;
- case 'U':
- case 'u':
- subm = 4;
- goto real_programmers_use_gotos;
- break;
- case 'O':
- case 'o':
- subm = SUBM_OKAY;
- real_programmers_use_gotos:
- c = 'n';
- quit = 1;
- break;
- case ' 33':
- case 'r':
- case 'n':
- quit = 1;
- break;
- default:
- break;
- }
- if(c != ' ')
- click_time = (time_t) 0;
- if(cur < top) {
- top--;
- prdir(main_w, top, top, dirdat, longest);
- }
- if(cur - top > main_w->ys - (2 + FILE_MWTR)) {
- top++;
- prdir(main_w, top, top, dirdat, longest);
- }
- /*
- if(cur != ocur)
- wlocate(main_w, 0, cur + FILE_MWTR - top);
- */
- ocur = cur;
- dhili(subm);
- /* this really needs to go in dhili !!!*/
- wlocate(main_w, 0, cur + FILE_MWTR - top);
- }
- quit = 0;
- /* ESC means quit */
- if(c == ' 33') {
- wclose(main_w, 1);
- wclose(dsub, 1);
- free(dirdat);
- return(NULL);
- }
- /* Page up or down ? */
- if(pgud == 1) { /* Page up */
- ocur = top;
- top -= main_w->ys - (1 + FILE_MWTR);
- if(top < 0)
- top = 0;
- cur = top;
- pgud = 0;
- if(ocur != top)
- prdir(main_w, top, cur, dirdat, longest);
- ocur = cur;
- goto again;
- }
- if(pgud == 2) { /* Page down */
- ocur = top;
- if(top < nrents - main_w->ys + (1 + FILE_MWTR)) {
- top += main_w->ys - (1 + FILE_MWTR);
- if(top > nrents - main_w->ys + (1 + FILE_MWTR)) {
- top = nrents - main_w->ys + (1 + FILE_MWTR);
- }
- cur = top;
- } else
- cur = nrents - 1;
- pgud = 0;
- if(ocur != top)
- prdir(main_w, top, cur, dirdat, longest);
- ocur = cur;
- goto again;
- }
- if(c =='r' || c == 'n') {
- switch(subm) {
- case 0:
- /* Goto directory */
- {
- char buf[128];
- char *s;
- strncpy(buf, down_loading? P_DOWNDIR : P_UPDIR,
- sizeof(buf) -1);
- s = input(_("Goto directory:"), buf);
- /* if(s == CNULL || *s == (char) 0) */
- if(s == CNULL)
- break;
- goto_filedir(buf, 1);
- }
- break;
- case 1:
- /* Previous directory */
- goto_filedir(prev_dir, 1);
- break;
- case 2:
- /* File (wildcard) spec */
- {
- char *s = input(_("Filename pattern:"), wc_mem);
- if(s == CNULL || *s == (char) 0)
- break;
- strcpy(wc_str, wc_mem);
- new_filedir(dirdat, 1);
- wc_str[0] = (char) 0;
- }
- break;
- case 3:
- /* Tag */
- if(how_many == 1)
- file_tell(_("Can select only one!"));
- else if(how_many == -1) {
- char tag_buf[128];
- char *s;
- strncpy(tag_buf, wc_mem, 128);
-
- s = input(_("Tag pattern:"), tag_buf);
- if(s != CNULL && *s != (char) 0) {
- int newly_tagged;
- if((newly_tagged = tag_untag(tag_buf, 1)) == 0) {
- file_tell(_("No file(s) tagged"));
- goto tag_end;
- }
- tag_cnt += newly_tagged;
- prdir(main_w, top, top, dirdat, longest);
- }
- }
- tag_end:
- break;
- case 4:
- /* Untag */
- {
- char tag_buf[128];
- char *s;
- int untagged;
- strncpy(tag_buf, wc_mem, 128);
-
- s = input(_("Untag pattern:"), tag_buf);
- if(s == CNULL || *s == (char) 0)
- goto untag_end;
- if((untagged = tag_untag(tag_buf, 0)) == 0) {
- file_tell(_("No file(s) untagged"));
- goto untag_end;
- }
- tag_cnt -= untagged;
- prdir(main_w, top, top, dirdat, longest);
- }
- untag_end:
- break;
- case 5:
- {
- /* Done */
- char *ret_ptr = NULL; /* failsafe: assume failure */
- if(how_many != 0 && !tag_cnt) {
- while(1) {
- s = input(_("No file selected - enter filename:"),
- ret_buf);
- if(s != CNULL && *s != (char) 0) {
- int f_exist = access(ret_buf, F_OK);
- if(down_loading) {
- if(f_exist != -1) {
- /* ask 'em if they're *sure* */
- char buf[BUFSIZ];
- snprintf(buf, sizeof(buf),
- _("File: "%s" exists!. Over-write?"),
- ret_buf);
- if(ask(buf, d_yesno) == 0) {
- ret_ptr = ret_buf;
- break;
- }
- }
- else {
- ret_ptr = ret_buf;
- break;
- }
- }
- else {
- if(f_exist == -1)
- file_tell(_("no such file!"));
- else {
- ret_ptr = ret_buf;
- break;
- }
- }
- }
- else {
- /* maybe want to ask: "abort?", here */
- goto again;
- }
- }
- }
- else {
- /* put 'em in a buffer for return */
- if(how_many == 0) {
- /* current working directory */
- ret_ptr = work_dir;
- }
- else {
- ret_ptr = concat_list(dirdat);
- }
- }
- wclose(main_w, 1);
- wclose(dsub, 1);
- free(dirdat);
- return(ret_ptr);
- }
- break;
- default:
- /* should "beep", I guess (? shouldn't get here) */
- file_tell("BEEP!");
- break;
- } /* switch */
- }
- goto again;
- }