/* This file is part of Mailfromd. -*- c -*- Copyright (C) 2008 Sergey Poznyakoff 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 3, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include MF_VAR(optarg, STRING); MF_VAR(optind, NUMBER); MF_VAR(opterr, NUMBER); MF_VAR(optopt, STRING); MF_DEFUN_VARARGS(getopt, STRING, NUMBER argc, NUMBER argoff) { int rc; int long_idx; char s[2] = { 0, 0 }; static char xargc; static char **xargv; static struct option *option; static char *optstr; static char *loptstr; if (argc) { size_t i, n; size_t serial = 256; xargc = argc + 1; xargv = xcalloc(xargc+1, sizeof(xargv[0])); xargv[0] = script_file; for (i = 0; i < argc; i++) xargv[i+1] = MF_VASTRING(argoff + i); xargv[i+1] = NULL; n = MF_VA_COUNT(); if (n) { size_t i, j; size_t len; char *str; size_t size, lsize, lcnt; MF_VA_START(); size = lsize = lcnt = 0; for (i = 0; i < n; i++) { MF_VA_ARG(i, STRING, str); len = strcspn(str, "|"); size += len; if (str[len]) { lcnt++; lsize += strlen(str + len); } } optstr = xrealloc(optstr, size + 1); loptstr = xrealloc(loptstr, lsize + 1); option = xrealloc(option, (lcnt + 1) * sizeof(option[0])); size = 0; lsize = 0; for (i = j = 0; i < n; i++) { size_t len; int val; MF_VA_ARG(i, STRING, str); len = strcspn(str, "|"); if (len > 0) { memcpy(optstr + size, str, len); size += len; val = str[0]; } else val = serial++; if (str[len]) { option[j].name = loptstr + lsize; strcpy(loptstr + lsize, str + len + 1); lsize += strlen(str + len) + 1; if (str[1] == ':') option[j].has_arg = (str[2] == ':') ? optional_argument : required_argument; else option[j].has_arg = no_argument; option[j].flag = NULL; option[j].val = val; j++; } } MF_VA_END(); optstr[size] = 0; loptstr[lsize] = 0; memset(&option[j], 0, sizeof option[0]); } else option = NULL; } if (xargc == 0 || optstr == NULL || option == 0) MF_RETURN_STRING(""); optind = (int) MF_VAR_REF(optind); opterr = (int) MF_VAR_REF(opterr); rc = getopt_long(xargc, xargv, optstr, option, &long_idx); MF_VAR_REF(optind, optind); MF_VAR_REF(opterr, opterr); s[0] = optopt; MF_VAR_SET_STRING(optopt, s); MF_VAR_SET_STRING(optarg, optarg); if (rc == EOF) MF_RETURN_STRING(""); if (rc < 256) { s[0] = rc; MF_RETURN_STRING(s); } MF_RETURN_STRING(option[long_idx].name); } END MF_INIT( struct value val; val.type = dtype_number; val.v.number = 1; ensure_initialized_variable("opterr", &val); )