(********************************************************************)
(*                                                                  *)
(*  soc_act.s7i   Generate code for actions of primitive sockets.   *)
(*  Copyright (C) 1990 - 1994, 2004 - 2014  Thomas Mertes           *)
(*                                                                  *)
(*  This file is part of the Seed7 compiler.                        *)
(*                                                                  *)
(*  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.             *)
(*                                                                  *)
(*  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, write to the           *)
(*  Free Software Foundation, Inc., 51 Franklin Street,             *)
(*  Fifth Floor, Boston, MA  02110-1301, USA.                       *)
(*                                                                  *)
(********************************************************************)


const ACTION: SOC_ACCEPT           is action "SOC_ACCEPT";
const ACTION: SOC_ADDR_FAMILY      is action "SOC_ADDR_FAMILY";
const ACTION: SOC_ADDR_NUMERIC     is action "SOC_ADDR_NUMERIC";
const ACTION: SOC_ADDR_SERVICE     is action "SOC_ADDR_SERVICE";
const ACTION: SOC_BIND             is action "SOC_BIND";
const ACTION: SOC_CLOSE            is action "SOC_CLOSE";
const ACTION: SOC_CONNECT          is action "SOC_CONNECT";
const ACTION: SOC_CPY              is action "SOC_CPY";
const ACTION: SOC_EMPTY            is action "SOC_EMPTY";
const ACTION: SOC_EQ               is action "SOC_EQ";
const ACTION: SOC_GETC             is action "SOC_GETC";
const ACTION: SOC_GETS             is action "SOC_GETS";
const ACTION: SOC_GET_HOSTNAME     is action "SOC_GET_HOSTNAME";
const ACTION: SOC_GET_LOCAL_ADDR   is action "SOC_GET_LOCAL_ADDR";
const ACTION: SOC_GET_PEER_ADDR    is action "SOC_GET_PEER_ADDR";
const ACTION: SOC_HAS_NEXT         is action "SOC_HAS_NEXT";
const ACTION: SOC_INET_ADDR        is action "SOC_INET_ADDR";
const ACTION: SOC_INET_LOCAL_ADDR  is action "SOC_INET_LOCAL_ADDR";
const ACTION: SOC_INET_SERV_ADDR   is action "SOC_INET_SERV_ADDR";
const ACTION: SOC_INPUT_READY      is action "SOC_INPUT_READY";
const ACTION: SOC_LINE_READ        is action "SOC_LINE_READ";
const ACTION: SOC_LISTEN           is action "SOC_LISTEN";
const ACTION: SOC_NE               is action "SOC_NE";
const ACTION: SOC_ORD              is action "SOC_ORD";
const ACTION: SOC_RECV             is action "SOC_RECV";
const ACTION: SOC_SEND             is action "SOC_SEND";
const ACTION: SOC_SET_OPT_BOOL     is action "SOC_SET_OPT_BOOL";
const ACTION: SOC_SOCKET           is action "SOC_SOCKET";
const ACTION: SOC_VALUE            is action "SOC_VALUE";
const ACTION: SOC_WORD_READ        is action "SOC_WORD_READ";
const ACTION: SOC_WRITE            is action "SOC_WRITE";


const proc: soc_prototypes (inout file: c_prog) is func

  begin
    declareExtern(c_prog, "socketType  socAccept (const const_socketType, bstriType *const);");
    declareExtern(c_prog, "intType     socAddrFamily (const const_bstriType);");
    declareExtern(c_prog, "striType    socAddrNumeric (const const_bstriType);");
    declareExtern(c_prog, "striType    socAddrService (const const_bstriType);");
    declareExtern(c_prog, "void        socBind (const const_socketType, const_bstriType);");
    declareExtern(c_prog, "void        socClose (const socketType);");
    declareExtern(c_prog, "void        socConnect (const const_socketType, const_bstriType);");
    declareExtern(c_prog, "void        socCpy (socketType *const, const socketType);");
    declareExtern(c_prog, "void        socCpyGeneric (genericType *const, const genericType);");
    declareExtern(c_prog, "socketType  socCreate (const socketType);");
    declareExtern(c_prog, "genericType socCreateGeneric (const genericType);");
    declareExtern(c_prog, "void        socDestr (const socketType);");
    declareExtern(c_prog, "void        socDestrGeneric (const genericType);");
    declareExtern(c_prog, "charType    socGetc (const const_socketType, charType *const);");
    declareExtern(c_prog, "striType    socGets (const const_socketType, intType, charType *const);");
    declareExtern(c_prog, "striType    socGetHostname(void);");
    declareExtern(c_prog, "bstriType   socGetLocalAddr (const const_socketType);");
    declareExtern(c_prog, "bstriType   socGetPeerAddr (const const_socketType);");
    declareExtern(c_prog, "boolType    socHasNext (const const_socketType);");
    declareExtern(c_prog, "bstriType   socInetAddr (const const_striType, intType);");
    declareExtern(c_prog, "bstriType   socInetLocalAddr (intType);");
    declareExtern(c_prog, "bstriType   socInetServAddr (intType);");
    declareExtern(c_prog, "boolType    socInputReady (const const_socketType, intType, intType);");
    declareExtern(c_prog, "striType    socLineRead (const const_socketType, charType *const);");
    declareExtern(c_prog, "void        socListen (const const_socketType, intType);");
    declareExtern(c_prog, "intType     socOrd (const const_socketType);");
    declareExtern(c_prog, "intType     socRecv (const const_socketType, striType *const, intType, intType);");
    declareExtern(c_prog, "intType     socRecvfrom (const const_socketType, striType *const, intType, intType, bstriType *const);");
    declareExtern(c_prog, "intType     socSend (const const_socketType, const_striType, intType);");
    declareExtern(c_prog, "intType     socSendto (const const_socketType, const_striType, intType, bstriType);");
    declareExtern(c_prog, "void        socSetOptBool (const const_socketType, intType, boolType);");
    declareExtern(c_prog, "socketType  socSocket (intType, intType, intType);");
    declareExtern(c_prog, "striType    socWordRead (const const_socketType, charType *const);");
    declareExtern(c_prog, "void        socWrite (const const_socketType, const const_striType);");
    declareExtern(c_prog, "socketType  socValue (const const_objRefType);");
  end func;


const proc: process (SOC_ACCEPT, in reference: function,
    in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_socket_result(c_expr);
    c_expr.result_expr &:= "socAccept(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ", &(";
    getStdParamToResultExpr(params[2], c_expr);
    c_expr.result_expr &:= "))";
  end func;


const proc: process (SOC_ADDR_FAMILY, in reference: function,
    in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "socAddrFamily(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process (SOC_ADDR_NUMERIC, in reference: function,
    in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_stri_result(c_expr);
    c_expr.result_expr := "socAddrNumeric(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process (SOC_ADDR_SERVICE, in reference: function,
    in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_stri_result(c_expr);
    c_expr.result_expr := "socAddrService(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process (SOC_BIND, in reference: function,
    in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "socBind(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    getAnyParamToExpr(params[2], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process (SOC_CLOSE, in reference: function,
    in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "socClose(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process (SOC_CONNECT, in reference: function,
    in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "socConnect(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    getAnyParamToExpr(params[2], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process (SOC_CPY, in reference: function,
    in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: statement is expr_type.value;
    var expr_type: c_param1 is expr_type.value;
    var expr_type: c_param3 is expr_type.value;
  begin
    statement.temp_num := c_expr.temp_num;
    prepareAnyParamTemporarys(params[1], c_param1, statement);
    c_param3.demand := ASSIGN_RESULT;
    prepareAnyParamTemporarys(params[3], c_param3, statement);
    if c_param3.result_expr <> "" then
      statement.temp_decls &:= "socketType new_socket;\n";
      statement.expr &:= "new_socket=";
      statement.expr &:= c_param3.result_expr;
      statement.expr &:= ";\n";
      if isNormalVariable(params[1]) then
        statement.expr &:= "socDestr(";
        statement.expr &:= c_param1.expr;
        statement.expr &:= ");\n";
        statement.expr &:= c_param1.expr;
        statement.expr &:= "=new_socket;\n";
      else
        statement.temp_decls &:= "socketType *socket_ptr=&(";
        statement.temp_decls &:= c_param1.expr;
        statement.temp_decls &:= ");\n";
        statement.expr &:= "socDestr(*socket_ptr);\n";
        statement.expr &:= "*socket_ptr=new_socket;\n";
      end if;
    else
      statement.expr &:= "socCpy(&(";
      statement.expr &:= c_param1.expr;
      statement.expr &:= "), ";
      statement.expr &:= c_param3.expr;
      statement.expr &:= ");\n";
    end if;
    doLocalDeclsOfStatement(statement, c_expr);
  end func;


const proc: process (SOC_EMPTY, in reference: function,
    in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "&emptySocketRecord";
  end func;


const proc: process (SOC_EQ, in reference: function,
    in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ") == (";
    getAnyParamToExpr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process (SOC_GETC, in reference: function,
    in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "socGetc(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", &(";
    process_expr(params[2], c_expr);
    c_expr.expr &:= "))";
  end func;


const proc: process (SOC_GETS, in reference: function,
    in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_stri_result(c_expr);
    c_expr.result_expr := "socGets(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ", ";
    getStdParamToResultExpr(params[2], c_expr);
    c_expr.result_expr &:= ", &(";
    getStdParamToResultExpr(params[3], c_expr);
    c_expr.result_expr &:= "))";
  end func;


const proc: process (SOC_GET_HOSTNAME, in reference: function,
    in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_stri_result(c_expr);
    c_expr.result_expr := "socGetHostname()";
  end func;


const proc: process (SOC_GET_LOCAL_ADDR, in reference: function,
    in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_bstri_result(c_expr);
    c_expr.result_expr := "socGetLocalAddr(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process (SOC_GET_PEER_ADDR, in reference: function,
    in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_bstri_result(c_expr);
    c_expr.result_expr := "socGetPeerAddr(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process (SOC_HAS_NEXT, in reference: function,
    in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "socHasNext(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process (SOC_INET_ADDR, in reference: function,
    in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_bstri_result(c_expr);
    c_expr.result_expr := "socInetAddr(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ", ";
    getStdParamToResultExpr(params[2], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process (SOC_INET_LOCAL_ADDR, in reference: function,
    in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_bstri_result(c_expr);
    c_expr.result_expr := "socInetLocalAddr(";
    getStdParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process (SOC_INET_SERV_ADDR, in reference: function,
    in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_bstri_result(c_expr);
    c_expr.result_expr := "socInetServAddr(";
    getStdParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process (SOC_INPUT_READY, in reference: function,
    in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "socInputReady(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process (SOC_LINE_READ, in reference: function,
    in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_stri_result(c_expr);
    c_expr.result_expr := "socLineRead(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ", &(";
    getStdParamToResultExpr(params[2], c_expr);
    c_expr.result_expr &:= "))";
  end func;


const proc: process (SOC_LISTEN, in reference: function,
    in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "socListen(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process (SOC_NE, in reference: function,
    in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ") != (";
    getAnyParamToExpr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process (SOC_ORD, in reference: function,
    in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "socOrd(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process (SOC_RECV, in reference: function,
    in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "socRecv(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", &(";
    process_expr(params[2], c_expr);
    c_expr.expr &:= "), ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[4], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process (SOC_SEND, in reference: function,
    in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "socSend(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    getAnyParamToExpr(params[2], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process (SOC_SET_OPT_BOOL, in reference: function,
    in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "socSetOptBool(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process (SOC_SOCKET, in reference: function,
    in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_socket_result(c_expr);
    c_expr.result_expr &:= "socSocket(";
    getStdParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ", ";
    getStdParamToResultExpr(params[2], c_expr);
    c_expr.result_expr &:= ", ";
    getStdParamToResultExpr(params[3], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process (SOC_VALUE, in reference: function,
    in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_socket_result(c_expr);
    c_expr.result_expr &:= "socValue(";
    getStdParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process (SOC_WORD_READ, in reference: function,
    in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_stri_result(c_expr);
    c_expr.result_expr := "socWordRead(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ", &(";
    getStdParamToResultExpr(params[2], c_expr);
    c_expr.result_expr &:= "))";
  end func;


const proc: process (SOC_WRITE, in reference: function,
    in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "socWrite(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    getAnyParamToExpr(params[2], c_expr);
    c_expr.expr &:= ");\n";
  end func;