"Fossies" - the Fresh Open Source Software Archive

Member "cook-2.34/cook/builtin/write.c" (25 Sep 2010, 5615 Bytes) of package /linux/misc/old/cook-2.34.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "write.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  *      cook - file construction tool
    3  *      Copyright (C) 1999, 2001, 2004, 2006-2009 Peter Miller
    4  *
    5  *      This program is free software; you can redistribute it and/or modify
    6  *      it under the terms of the GNU General Public License as published by
    7  *      the Free Software Foundation; either version 3 of the License, or
    8  *      (at your option) any later version.
    9  *
   10  *      This program is distributed in the hope that it will be useful,
   11  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
   12  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   13  *      GNU General Public License for more details.
   14  *
   15  *      You should have received a copy of the GNU General Public License
   16  *      along with this program. If not, see
   17  *      <http://www.gnu.org/licenses/>.
   18  */
   19 
   20 #include <common/ac/stdio.h>
   21 #include <common/ac/string.h>
   22 
   23 #include <cook/builtin/write.h>
   24 #include <common/error_intl.h>
   25 #include <cook/expr/position.h>
   26 #include <common/fflush_slow.h>
   27 #include <common/str_list.h>
   28 #include <common/trace.h>
   29 
   30 
   31 /*
   32  * NAME
   33  *      builtin_write - builtin function for writing files
   34  *
   35  * SYNOPSIS
   36  *      int builtin_write(string_list_ty *result, string_list_ty *args);
   37  *
   38  * DESCRIPTION
   39  *      The builtin_write function is used to implement the
   40  *      "write" builtin function of cook to write text files.
   41  *
   42  * RETURNS
   43  *      int; 0 on success, -1 on any error
   44  *
   45  * CAVEAT
   46  *      This function is designed to be used as a "builtin" function.
   47  */
   48 
   49 static int
   50 interpret(string_list_ty *result, const string_list_ty *args,
   51     const struct expr_position_ty *pp, const struct opcode_context_ty *ocp)
   52 {
   53     string_ty       *fn;
   54     FILE            *fp;
   55     size_t          j;
   56     int             retval;
   57 
   58     trace(("write::interpret(result = %p, args = %p)\n{\n", result, args));
   59     (void)result;
   60     (void)ocp;
   61     retval = 0;
   62 
   63     /*
   64      * make sure we have at least the file name
   65      */
   66     if (args->nstrings < 2)
   67     {
   68         sub_context_ty  *scp;
   69 
   70         scp = sub_context_new();
   71         sub_var_set_string(scp, "Name", args->string[0]);
   72         error_with_position
   73         (
   74             pp,
   75             scp,
   76             i18n("$name: requires one or more arguments")
   77         );
   78         sub_context_delete(scp);
   79         retval = -1;
   80         goto dead;
   81     }
   82 
   83     /*
   84      * open the file
   85      *      on windows NT, it's specifically a text file
   86      */
   87     fn = args->string[1];
   88     fp = fopen(fn->str_text, "w");
   89     if (!fp)
   90     {
   91         error_intl_open(fn->str_text);
   92         retval = -1;
   93         goto dead;
   94     }
   95 
   96     /*
   97      * write the words, one per line
   98      */
   99     for (j = 2; j < args->nstrings; ++j)
  100     {
  101         string_ty      *s;
  102 
  103         s = args->string[j];
  104         fwrite(s->str_text, 1, s->str_length, fp);
  105         if (!s->str_length || s->str_text[s->str_length - 1] != '\n')
  106             fputc('\n', fp);
  107         if (ferror(fp))
  108         {
  109             error_intl_write(fn->str_text);
  110             fclose(fp);
  111             retval = -1;
  112             goto dead;
  113         }
  114     }
  115 
  116     /*
  117      * finish up writing the file
  118      */
  119     if (fflush_slowly(fp))
  120     {
  121         error_intl_write(fn->str_text);
  122         fclose(fp);
  123         retval = -1;
  124         goto dead;
  125     }
  126     if (fclose(fp))
  127     {
  128         error_intl_close(fn->str_text);
  129         retval = -1;
  130     }
  131 
  132     /*
  133      * all done
  134      */
  135     dead:
  136     trace(("return %d;\n", retval));
  137     trace(("}\n"));
  138     return retval;
  139 }
  140 
  141 
  142 static int
  143 strliststr(const string_list_ty *slp, string_ty *s)
  144 {
  145     size_t          j;
  146 
  147     for (j = 0; j < slp->nstrings; ++j)
  148         if (strstr(slp->string[j]->str_text, s->str_text))
  149             return 1;
  150     return 0;
  151 }
  152 
  153 
  154 static int
  155 script(string_list_ty *result, const string_list_ty *args,
  156     const struct expr_position_ty *pp, const struct opcode_context_ty *ocp)
  157 {
  158     size_t          j;
  159     int             retval;
  160     string_ty       *the_end;
  161     static int      the_end_n;
  162     string_ty       *s;
  163 
  164     trace(("write::script(result = %p, args = %p)\n{\n", result, args));
  165     (void)result;
  166     (void)ocp;
  167     retval = 0;
  168 
  169     /*
  170      * make sure we have at least the file name
  171      */
  172     if (args->nstrings < 2)
  173     {
  174         sub_context_ty  *scp;
  175 
  176         scp = sub_context_new();
  177         sub_var_set_string(scp, "Name", args->string[0]);
  178         error_with_position
  179         (
  180             pp,
  181             scp,
  182             i18n("$name: requires one or more arguments")
  183         );
  184         sub_context_delete(scp);
  185         retval = -1;
  186         goto dead;
  187     }
  188 
  189     /*
  190      * find a terminator
  191      */
  192     the_end = 0;
  193     for (;;)
  194     {
  195         int             n;
  196 
  197         n = ++the_end_n;
  198         the_end = str_format("the-end-%d", n);
  199         if (!strliststr(args, the_end))
  200             break;
  201         str_free(the_end);
  202     }
  203     assert(the_end);
  204 
  205     /*
  206      * Write out the start of the here-document
  207      */
  208     s = str_quote_shell(args->string[1]);
  209     printf("cat > %s << '%s'\n", s->str_text, the_end->str_text);
  210     str_free(s);
  211 
  212     /*
  213      * write the words, one per line
  214      */
  215     for (j = 2; j < args->nstrings; ++j)
  216     {
  217         s = args->string[j];
  218         fwrite(s->str_text, 1, s->str_length, stdout);
  219         if (!s->str_length || s->str_text[s->str_length - 1] != '\n')
  220             fputc('\n', stdout);
  221     }
  222 
  223     /*
  224      * write the end of the here-document
  225      */
  226     printf("%s\n", the_end->str_text);
  227     str_free(the_end);
  228 
  229     /*
  230      * all done
  231      */
  232     dead:
  233     trace(("return %d;\n", retval));
  234     trace(("}\n"));
  235     return retval;
  236 }
  237 
  238 
  239 builtin_ty builtin_write =
  240 {
  241     "write",
  242     interpret,
  243     script,
  244 };