[папа STL] Alexander Stepanov "Notes on Programming"
От: Вертер  
Дата: 06.02.07 00:03
Оценка: 104 (14)
Alexander Stepanov опубликовал лекции "Notes on Programming".

Alexander Stepanov: I have been programming for over 30 years. I wrote my first program in 1969 and became a full time programmer in 1972.
Re: [папа STL] Alexander Stepanov "Notes on Programming"
От: Шахтер Интернет  
Дата: 06.02.07 07:45
Оценка: +6
Здравствуйте, Вертер, Вы писали:

В>Alexander Stepanov опубликовал лекции "Notes on Programming".


В>Alexander Stepanov: I have been programming for over 30 years. I wrote my first program in 1969 and became a full time programmer in 1972.


В каждой програмистской конторе написать большими буквами и прибить к стене.

One could write beautiful code even in assembly. And if I could, I must.


Specifically I decided to use the following principles:

1. the code should be partitioned into functions;
2. every function should be most 20 lines of code;
3. functions should not depend on the global state but only on the arguments;
4. every function is either general or application specific, where general function is useful to other applications;
5. every function that could be made general – should be made general;
6. the interface to every function should be documented;
7. the global state should be documented by describing both semantics of individual variables and the global invariants.

The result of my experiment was quite astonishing. The code did not contain serious bugs. There were typos: I had to change AND to OR, etc. But I did not need patches. And over 95% of the code was in general functions! I felt quite proud.

В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[2]: [папа STL] Alexander Stepanov "Notes on Programming"
От: Аноним  
Дата: 06.02.07 08:01
Оценка: +1 :)
Здравствуйте, Шахтер, Вы писали:

Ш>Здравствуйте, Вертер, Вы писали:


В>>Alexander Stepanov опубликовал лекции "Notes on Programming".


В>>Alexander Stepanov: I have been programming for over 30 years. I wrote my first program in 1969 and became a full time programmer in 1972.


Ш>В каждой програмистской конторе написать большими буквами и прибить к стене.


Ш>

Ш>One could write beautiful code even in assembly. And if I could, I must.


Ну да...
Только производительность 30 строк ассемблерного кода в день
это не то же самое, что и 30 строк кода на C++
Т.е. в строчках получается одинаково, но строчки "весят" по-разному.

Ш>

Ш>Specifically I decided to use the following principles:

Ш>1. the code should be partitioned into functions;
Ш>2. every function should be most 20 lines of code;
Ш>3. functions should not depend on the global state but only on the arguments;
Ш>4. every function is either general or application specific, where general function is useful to other applications;
Ш>5. every function that could be made general – should be made general;
Ш>6. the interface to every function should be documented;
Ш>7. the global state should be documented by describing both semantics of individual variables and the global invariants.

Ш>The result of my experiment was quite astonishing. The code did not contain serious bugs. There were typos: I had to change AND to OR, etc. But I did not need patches. And over 95% of the code was in general functions! I felt quite proud.


Тут прибивать на стену нечего.
Это почти в каждой нормальной фирме оформлено как "coding standards"
с кучей checklists.
Все эти простые правила практически всем известны.
Но они работают только тогда, когда их последовательно и везде применяют.
Т.е. проблема не в правилах, а в дисциплине их применения.
Re[3]: [папа STL] Alexander Stepanov "Notes on Programming"
От: Шахтер Интернет  
Дата: 06.02.07 09:53
Оценка: :)
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, Шахтер, Вы писали:


Ш>>Здравствуйте, Вертер, Вы писали:


В>>>Alexander Stepanov опубликовал лекции "Notes on Programming".


В>>>Alexander Stepanov: I have been programming for over 30 years. I wrote my first program in 1969 and became a full time programmer in 1972.


Ш>>В каждой програмистской конторе написать большими буквами и прибить к стене.


Ш>>

Ш>>One could write beautiful code even in assembly. And if I could, I must.


А>Ну да...

А>Только производительность 30 строк ассемблерного кода в день
А>это не то же самое, что и 30 строк кода на C++
А>Т.е. в строчках получается одинаково, но строчки "весят" по-разному.

А это тут причем?

Ш>>

Ш>>Specifically I decided to use the following principles:

Ш>>1. the code should be partitioned into functions;
Ш>>2. every function should be most 20 lines of code;
Ш>>3. functions should not depend on the global state but only on the arguments;
Ш>>4. every function is either general or application specific, where general function is useful to other applications;
Ш>>5. every function that could be made general – should be made general;
Ш>>6. the interface to every function should be documented;
Ш>>7. the global state should be documented by describing both semantics of individual variables and the global invariants.

Ш>>The result of my experiment was quite astonishing. The code did not contain serious bugs. There were typos: I had to change AND to OR, etc. But I did not need patches. And over 95% of the code was in general functions! I felt quite proud.


А>Тут прибивать на стену нечего.

А>Это почти в каждой нормальной фирме оформлено как "coding standards"

Coding standards -- это нечто иное.

А>с кучей checklists.

А>Все эти простые правила практически всем известны.

Почти никому не известны. Достаточно код почитать, который эти "все" пишут.

А>Но они работают только тогда, когда их последовательно и везде применяют.

А>Т.е. проблема не в правилах, а в дисциплине их применения.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[3]: [папа STL] Alexander Stepanov "Notes on Programming"
От: Аноним  
Дата: 06.02.07 10:00
Оценка: +2 :)
А>Тут прибивать на стену нечего.
А>Это почти в каждой нормальной фирме оформлено как "coding standards"
А>с кучей checklists.
А>Все эти простые правила практически всем известны.
А>Но они работают только тогда, когда их последовательно и везде применяют.
А>Т.е. проблема не в правилах, а в дисциплине их применения.

И тем не менее, постоянно плодятся горы говно-кода. Знаю о некоем проекте. Кошмар страшенный, кода — уже за миллион(ы?) строк перевалило. Считают себя немерянными профессионалами, на уровне незыблемых истин — запрет использования СТЛ (дада, они до сих пор уверены, что компиляторы С++ — плохие и с шаблонами все плохо), У них тоже много жестких правил, которым они неукоснительно следуют. Но толку увы, нет. Навороты в дизайне такие, что мифические индусы, которых так любят обсуждать, плачут от зависти. Все течет, падает, жрет память гигами, работает медленно, как будто на жаве или питоне писали. Отчаявшись что-то улучшить, постоянно придумывают новые правила. Недавно решили использовать ворнинг -Weff++ или что там, так теперь заняты тем, что забивают тысячи строк ворнингов фиктивными определениями конструкторов копирования и операторов присваивания, после вызова которых все все равно радостно падает. Они — дисциплинированы, но увы, толку нет.
Потому как одно дело то, что человек считает своими принципами и другое, что ему навязывают.
Re[2]: [папа STL] Alexander Stepanov "Notes on Programming"
От: Lorenzo_LAMAS  
Дата: 06.02.07 10:12
Оценка: 6 (1) +2 :)))
Здравствуйте, Шахтер, Вы писали:

Ш>В каждой програмистской конторе написать большими буквами и прибить к стене.


Это в башку надо вбивать, а не на стены
Of course, the code must be complete enough to compile and link.
Re[4]: [папа STL] Alexander Stepanov "Notes on Programming"
От: Аноним  
Дата: 06.02.07 10:20
Оценка:
Здравствуйте, Шахтер, Вы писали:

Ш>Здравствуйте, Аноним, Вы писали:


А>>Здравствуйте, Шахтер, Вы писали:


Ш>>>Здравствуйте, Вертер, Вы писали:


В>>>>Alexander Stepanov опубликовал лекции "Notes on Programming".


В>>>>Alexander Stepanov: I have been programming for over 30 years. I wrote my first program in 1969 and became a full time programmer in 1972.


Ш>>>В каждой програмистской конторе написать большими буквами и прибить к стене.


Ш>>>

Ш>>>One could write beautiful code even in assembly. And if I could, I must.


А>>Ну да...

А>>Только производительность 30 строк ассемблерного кода в день
А>>это не то же самое, что и 30 строк кода на C++
А>>Т.е. в строчках получается одинаково, но строчки "весят" по-разному.

Ш>А это тут причем?

Да в общем ни причем. Так, реплика в тему (или не в тему )...

Ш>>>

Ш>>>Specifically I decided to use the following principles:

Ш>>>1. the code should be partitioned into functions;
Ш>>>2. every function should be most 20 lines of code;
Ш>>>3. functions should not depend on the global state but only on the arguments;
Ш>>>4. every function is either general or application specific, where general function is useful to other applications;
Ш>>>5. every function that could be made general – should be made general;
Ш>>>6. the interface to every function should be documented;
Ш>>>7. the global state should be documented by describing both semantics of individual variables and the global invariants.

Ш>>>The result of my experiment was quite astonishing. The code did not contain serious bugs. There were typos: I had to change AND to OR, etc. But I did not need patches. And over 95% of the code was in general functions! I felt quite proud.


А>>Тут прибивать на стену нечего.

А>>Это почти в каждой нормальной фирме оформлено как "coding standards"

Ш>Coding standards -- это нечто иное.

А что это? Те же самые рекомендации по форматированию и структурированию кода.
В нашем есть практически все, о чем пишет Stepanov.
Ну разве только "the code should be partitioned into functions" в явном виде отсутстует,
ввиду очевидности правила.

А>>с кучей checklists.

А>>Все эти простые правила практически всем известны.

Ш>Почти никому не известны. Достаточно код почитать, который эти "все" пишут.


Ну про "every function should be most 20 lines of code" я уже знал на 1-м курсе.
Твоя фраза только поддверждает мое наблюдение,
что проблема не в том, что народ не знает об этих простых правилах,
а в том, что правила не применяются .
Кстати, я почти уверен, что если тебя кто-то постоянно будет долбить,
по всем этим пунктам, то ты его довольно быстро начнешь посылать куда подальше.
Или ты прямо сейчас перестанешь писать функции длиннее 20 строк?

Но в принципе польза от правил от Степанова есть.
Одно дело когда их озвучит уважаемый в программистком мире человек.
И совсем другое дело, когда о них раскажет препод на скучней лекции по технологии программирования
или кто-то напишет это в мало кем читаемом coding standards/guidelines
Re[4]: [папа STL] Alexander Stepanov "Notes on Programming"
От: Аноним  
Дата: 06.02.07 10:26
Оценка: :))
Здравствуйте, Аноним, Вы писали:

А>>Тут прибивать на стену нечего.

А>>Это почти в каждой нормальной фирме оформлено как "coding standards"
А>>с кучей checklists.
А>>Все эти простые правила практически всем известны.
А>>Но они работают только тогда, когда их последовательно и везде применяют.
А>>Т.е. проблема не в правилах, а в дисциплине их применения.

А>И тем не менее, постоянно плодятся горы говно-кода.


Ну дак это вечная проблема, причем не только в программировании
Вроде в теории все должно быть хорошо, а вот людишки не те...
Re[3]: [папа STL] Alexander Stepanov "Notes on Programming"
От: Анатолий Широков СССР  
Дата: 06.02.07 14:00
Оценка: +1
Здравствуйте, Lorenzo_LAMAS, Вы писали:

L_L>Здравствуйте, Шахтер, Вы писали:


Ш>>В каждой програмистской конторе написать большими буквами и прибить к стене.


L_L>Это в башку надо вбивать, а не на стены


А если не вбивается, то сносить такую башку напрочь.
Re[4]: [папа STL] Alexander Stepanov "Notes on Programming"
От: Аноним  
Дата: 06.02.07 14:02
Оценка:
Здравствуйте, Анатолий Широков, Вы писали:

АШ>Здравствуйте, Lorenzo_LAMAS, Вы писали:


L_L>>Здравствуйте, Шахтер, Вы писали:


Ш>>>В каждой програмистской конторе написать большими буквами и прибить к стене.


L_L>>Это в башку надо вбивать, а не на стены


АШ>А если не вбивается, то сносить такую башку напрочь.


Да господа....
Вам в Армию надо программировать.
Re[3]: [папа STL] Alexander Stepanov "Notes on Programming"
От: Nuzhny Россия https://github.com/Nuzhny007
Дата: 06.02.07 14:22
Оценка:
Здравствуйте, Lorenzo_LAMAS, Вы писали:

L_L>Здравствуйте, Шахтер, Вы писали:


Ш>>В каждой програмистской конторе написать большими буквами и прибить к стене.


L_L>Это в башку надо вбивать, а не на стены


Удивляюсь я вам всем: вбивать, учить...

Обучение получается гораздо проще по-другому: есть требования к проекту, есть сроки.
Не готово, не работает — лишение премии. Регулярный срыв — увольнение.

С такими требованиями люди сами научатся оптимизировать свою работу, выбирать правильные coding styles. Иначе — зачем такие программисты.
Re[3]: [папа STL] Alexander Stepanov "Notes on Programming"
От: Шахтер Интернет  
Дата: 06.02.07 14:56
Оценка: :))
Здравствуйте, Lorenzo_LAMAS, Вы писали:

L_L>Здравствуйте, Шахтер, Вы писали:


Ш>>В каждой програмистской конторе написать большими буквами и прибить к стене.


L_L>Это в башку надо вбивать, а не на стены


Знаешь как в Самсунге учат английскому?
В туалете выше писуаров на уровне глаз вешают листочки с английскими словами. Листочки регулярно меняют.
Видимо, помогает.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[5]: [папа STL] Alexander Stepanov "Notes on Programming"
От: Анатолий Широков СССР  
Дата: 06.02.07 15:20
Оценка: +1
АШ>>А если не вбивается, то сносить такую башку напрочь.

А>Да господа....

А>Вам в Армию надо программировать.

Нет, просто наболело.
Re[2]: [папа STL] Alexander Stepanov "Notes on Programming"
От: Константин Л. Франция  
Дата: 06.02.07 15:22
Оценка: +1
Здравствуйте, Шахтер, Вы писали:

[]

+1

Но вот 20 строк не всегда получается. Имхо это иногда даже вредно.
Re[3]: [папа STL] Alexander Stepanov "Notes on Programming"
От: Шахтер Интернет  
Дата: 06.02.07 15:46
Оценка: +1 :)
Здравствуйте, Константин Л., Вы писали:

КЛ>Здравствуйте, Шахтер, Вы писали:


КЛ>[]


КЛ>+1


КЛ>Но вот 20 строк не всегда получается. Имхо это иногда даже вредно.


Разумеется, следование данному правилу (как и остальным) нельзя доводить до абсурда.
Но писать вот такие функции...


unsigned short
IsakmpSaCls::ProcessMainMode(isakmp_hdr *hdr, IsakmpSaCls **delSa,
                             ERROR_CODE &error)
{
  sa_payload *sap;
  proposal_payload *prop;
  isakmp_hdr *newhdr;
  key_x_payload *keyp;
  nonce_payload *nonceI, *nonceR;
  id_payload *idp;
  hash_payload *hashp;
  cert_payload *cert;
  notify_payload *notify;
  vendor_id_payload *vend, *vend1 = 0; // Q00959911 introduces vend1
  IsakmpSaCls *testSa;
  IsakmpCallBackStr *cb;
  UINT8 *idData = 0;
  UINT8 *certData, *sigData;
  unsigned int idLen = 0;
  unsigned int sizeofCertPayload = 5;
  unsigned int ourKeySize;
  unsigned int badKeySize = IKEDHCls::PublicValueLength(saDHGroup, BAD_AES); // too early for aesCompatOn (sometimes)
  UINT16 hashlen, certLen;
  UINT16 isaError = AUTH_FAILED;
  ERROR_CODE localError = SUCCESS;
  UINT8 uidType, initiatorIdType = 0;

  if (aesCompatOn == BAD_AES)
  {
      ourKeySize = IKEDHCls::PublicValueLength(saDHGroup, BAD_AES);
  }
  else
  {
      ourKeySize = IKEDHCls::PublicValueLength(saDHGroup);
  }

  // The following is an adjustment made to cope with "version 3" (2.0)
  // clients and servers, which used sizeof(cert_payload) throughout the
  // code and thus placed the start of the certificate data one byte later
  // than it should be...
  if ((saCESVersion == 3) || (saNewOakVersion == 3))
    sizeofCertPayload = 6;
  switch (saState)
  {
    case OAK_MM_SA_SETUP:
      // Make sure we actually got back an SA payload...
      sap = (sa_payload *)IsakmpFindPayload(hdr, ISA_SA);
      if (!sap)
        return 0xFFFF;
      // Find out what was accepted.
      prop = (proposal_payload *)((UINT8 *)sap + sizeof(sa_payload));
      if ((prop->prop_num != 1) || (prop->protocol_id != PROTO_ISAKMP) ||
          (prop->num_transforms != 1))
        {
          if ( isakmpVerbose )
            isakmpEventLog->Event(EventLog::DEBUG,
                                  "Proposal bad syntax: prop_num:%x protocol_id:%x transforms:%x",
                                  prop->prop_num, prop->protocol_id, prop->num_transforms);
          return PROPOSAL_BAD_SYNTAX;
        }

      // Check for the hash algorithm attribute.
      saHashAlg = GetBasicAttributeValue(prop, OAK_HASH_ALG);

      // CR147031: FIPS only allows SHA hashing, so enforce it here. Note: we only proposed SHA.
      if (  FIPSCls::Enabled() && ( saHashAlg == HASH_MD5 ) )
        {
          isakmpEventLog->Event(EventLog::DEBUG,
                                "Proposal rejected: FIPS requires SHA hashing algorithm. ");
        }

      if ((saHashAlg != HASH_MD5) && (saHashAlg != HASH_SHA))
        {
          if ( isakmpVerbose )
            isakmpEventLog->Event(EventLog::DEBUG,
                                  "Proposal bad syntax: hash Algorithm:%x", saHashAlg);
          return PROPOSAL_BAD_SYNTAX;
        }

      // Cool - we have an accepted proposal.  Set the responder's cookie
      // and lose the timer.
      SetResponderCookie((UINT32 *)hdr->resp_cookie);
      CancelTimer();
      // Check for a CES (server) version number.
      vend = (vendor_id_payload *)IsakmpFindPayload(hdr, ISA_VEND_ID);
      while (vend)
        {
          UINT32 *vendDataPtr = (UINT32 *)((UINT8 *)vend +
                                           sizeof(vendor_id_payload));
          if ((ntohs(vend->payload_len) == sizeof(vendor_id_payload) + 8) &&
#ifdef LITTLE_ENDIAN
              (*vendDataPtr == 0x53454E42)    // BNES
#else
              (*vendDataPtr == 0x424E4553)    // BNES
#endif
              )
            {
              saCESVersion = ntohl(*(vendDataPtr + 1));

              // CD_AES : obviously, we are a compatible version ; hence self test skipped; only peer is checked
#ifdef _DEBUG
              isakmpEventLog->Event(EventLog::MEDIUM, "mainmode saCESVersion = 0x%x", saCESVersion);
#endif
              if (saCESVersion < AES_COMPAT_VERSION)
              {
                  aesCompatOn = BAD_AES; // we are talking to old code
                  //updating ourKeySize to incorrect value for kluge to work
                  ourKeySize = badKeySize;
                  if (isakmpVerbose) printf("ProcessMainMode: updated aesCompatOn to 0x%x in this %x ourkeysz to %x saState %d\n", aesCompatOn, (UINT32)this, ourKeySize, saState);
              }
              if (saCESVersion < MTU_COMPAT_VERSION)
              {
                  this->mtuCompatState = MTU_NOT_OKAY;
              }
              else
              {
                  this->mtuCompatState = MTU_OKAY;
              }
              if (saCESVersion == 3)
                sizeofCertPayload = 6;
            }
          else if ((ntohs(vend->payload_len) == sizeof(vendor_id_payload) + 16))
            {
#ifdef LITTLE_ENDIAN
              if (*vendDataPtr == 0x13D7CAAF  &&        // DPD Vendor-id
                  (*(vendDataPtr+1) == 0xC9F1A168 ) &&
                  (*(vendDataPtr+2) == 0xFC96866B ) &&
                  (*(vendDataPtr+3) == 0x00015777 ))    // Major=01 Minor=00
#else
                if (*vendDataPtr == 0xAFCAD713 &&
                    (*(vendDataPtr+1) == 0x68A1F1C9 ) &&
                    (*(vendDataPtr+2) == 0x6B8696FC ) &&
                    (*(vendDataPtr+3) == 0x77570100 ))
#endif
                  {
                    saDPDVendIdReceived = TRUE; // Q00959911
                    //Q00553988 Phanton tunnels on Branch Office, to multiple different vendor platforms
                    if(saSession && saSession->GetAccount()->IsVendorIdEnabled())
                      if (saSession && saSession->GetAccount()->GetAllowDeadPeerDetection() )
                        saDPDExchange = TRUE;
                  }
            }

          vend = (vendor_id_payload *)IsakmpFindPayload((generic_payload*)vend, ISA_VEND_ID);
        }

      // We need to set up a new packet buffer, and start the Diffie-Hellman
      // process now.
      delete [] saMessage;
      saDH = new DHCls(saDHGroup, aesCompatOn);
      myDHPublic = new UINT8[ourKeySize];
      saMessageLength = sizeof(isakmp_hdr) + sizeof(key_x_payload)
                        + ourKeySize + sizeof(nonce_payload) + 20;
      if (saAuthMethod == RSA_SIG)
        {
          saMessageLength += sizeofCertPayload;
          if (saSession)
            {
              //DnCls *issueDn = GetValidIssuer (saSession, &localError);
              if (localError == SUCCESS)
                {
                  const char *issuer = GetIssuerName(saSession, &localError);
                  if (issuer)
                    {
                      int ca_len = strlen (issuer);
                      saMessageLength += ca_len;
                    }
                }
            }
        }
      
      saMessage = new UINT8[saMessageLength];
      if (!saDH || !myDHPublic || !saMessage)
      {
        // We lose big time!
        delete this;
        return 0xFFFF;
      }
      // Set up the ISAKMP header...
      GetCookies((UINT32 *)saMessage);
      newhdr = (isakmp_hdr *)saMessage;
#ifdef LITTLE_ENDIAN
      *((UINT32 *)saMessage+4) = 0x00021004;
#else
      *((UINT32 *)saMessage+4) = 0x04100200;
#endif

      newhdr->mess_id = 0;
      newhdr->len = htonl(saMessageLength);
      // ...and the key exchange payload...
      // We need to save our public value internally.
      keyp = (key_x_payload *)(saMessage + sizeof(isakmp_hdr));

      keyp->next_payload = ISA_NONCE;
      keyp->reserved = 0;
      keyp->payload_len = htons(sizeof(key_x_payload) + saDH->PublicValueLength());
#ifdef LOAD_TEST
      // NOTE: We request a semaphore here, because the current Diffie-Hellman
      // code is single-threaded.  This doesn't impact the server, where only
      // tIsakmp does D-H, but it does impact the load generator.
      semTake(ipsecTunnelTableSem, WAIT_FOREVER);
#endif
      if (FALSE == saDH->Setup(*isakmpRng, myDHPublic))
        {
          isakmpEventLog->Event(EventLog::HIGH,
                          "Error in Diffie-Hellman Setup, group=%u", (UINT32)saDHGroup);
          delete this;
          return 0xFFFF;
        }

#ifdef LOAD_TEST
      semGive(ipsecTunnelTableSem);
#endif

      bcopy((char *)myDHPublic, (char *)keyp + sizeof(key_x_payload),
            saDH->PublicValueLength());
      // ...and the nonce.
      // We need the nonce to generate SKEYID later, but we'll just save
      // it here in the message itself.
      nonceI = (nonce_payload *)((UINT8 *)keyp + sizeof(key_x_payload)
                                 + saDH->PublicValueLength());
      *((UINT16 *)nonceI) = 0;
      nonceI->payload_len = htons(sizeof(nonce_payload) + 20);
      isakmpRng->GetBlock((UINT8 *)nonceI + sizeof(nonce_payload), 20);

      if (saAuthMethod == RSA_SIG)
      {
        nonceI->next_payload = ISA_CERT_REQ;
        cert = (cert_payload *)((UINT8 *)nonceI + sizeof(nonce_payload) + 20);
        *((UINT16 *)cert) = 0;
        cert->payload_len = htons(sizeofCertPayload);
        cert->cert_spec = 4;

        if (saSession)
          {
            if (localError == SUCCESS)
              {
                const char *issuer = GetIssuerName(saSession, &localError);

                if (issuer)
                  {
                    char *p = (char *)cert;
                    int ca_len = strlen (issuer);
                    p += 5;
                    strcpy (p, issuer);
                    cert->payload_len = htons (sizeofCertPayload + ca_len);
                  }    
              }
          }
      }

      // All done... Reset our state and the retransmit timer.
      saState = OAK_MM_KEY_EXCH;
      SetTimer(TIMER_RETRY, saIsakmpTimeout);
      break;

    case OAK_MM_KEY_EXCH:

      // Need to have key exchange and nonce payloads.
      keyp = (key_x_payload *)IsakmpFindPayload(hdr, ISA_KE);
      if (!keyp)
        return 0xFFFF;
      nonceI = (nonce_payload *)IsakmpFindPayload(hdr, ISA_NONCE);
      if (!nonceI)
        return 0xFFFF;

      // Q00959911 - Begin
      // If receiving the DPD Vendor Id has been delayed up until this
      // point, process it now - the following code is replicated from
      // case OAK_MM_SA_SETUP
      if (!saDPDVendIdReceived)
        {
          vend1 = (vendor_id_payload *)IsakmpFindPayload(hdr, ISA_VEND_ID);
          while (vend1)
            {
              UINT32 *vendDataPtr = (UINT32 *)((UINT8 *)vend1 +
                                               sizeof(vendor_id_payload));
              if ((ntohs(vend1->payload_len) == sizeof(vendor_id_payload) + 8) &&
#ifdef LITTLE_ENDIAN
                  (*vendDataPtr == 0x53454E42)    // BNES
#else
                  (*vendDataPtr == 0x424E4553)    // BNES
#endif
                  )
                {
                  saCESVersion = ntohl(*(vendDataPtr + 1));

                  // CD_AES : obviously, we are a compatible version ; hence self test skipped; only peer is checked
#ifdef _DEBUG
                  isakmpEventLog->Event(EventLog::MEDIUM, "mainmode saCESVersion = 0x%x", saCESVersion);
#endif
                  if (saCESVersion < AES_COMPAT_VERSION)
                    {
                      aesCompatOn = BAD_AES; // we are talking to old code
                      //updating ourKeySize to incorrect value for kluge to work
                      ourKeySize = badKeySize;
                      if (isakmpVerbose) printf("ProcessMainMode: updated aesCompatOn to 0x%x in this %x ourkeysz to %x saState %d\n", aesCompatOn, (UINT32)this, ourKeySize, saState);
                    }
                  if (saCESVersion < MTU_COMPAT_VERSION)
                    {
                      this->mtuCompatState = MTU_NOT_OKAY;
                    }
                  else
                    {
                      this->mtuCompatState = MTU_OKAY;
                    }
                  if (saCESVersion == 3)
                    sizeofCertPayload = 6;
                }
              else if ((ntohs(vend1->payload_len) == sizeof(vendor_id_payload) + 16))
                {
#ifdef LITTLE_ENDIAN
                  if (*vendDataPtr == 0x13D7CAAF  &&        // DPD Vendor-id
                      (*(vendDataPtr+1) == 0xC9F1A168 ) &&
                      (*(vendDataPtr+2) == 0xFC96866B ) &&
                      (*(vendDataPtr+3) == 0x00015777 ))    // Major=01 Minor=00
#else
                    if (*vendDataPtr == 0xAFCAD713 &&
                        (*(vendDataPtr+1) == 0x68A1F1C9 ) &&
                        (*(vendDataPtr+2) == 0x6B8696FC ) &&
                        (*(vendDataPtr+3) == 0x77570100 ))
#endif
                      {
                        saDPDVendIdReceived = TRUE;
                        //Q00553988 Phanton tunnels on Branch Office, to multiple different vendor platforms
                        if(saSession && saSession->GetAccount()->IsVendorIdEnabled())
                          if (saSession && saSession->GetAccount()->GetAllowDeadPeerDetection() )
                            {
                              saDPDExchange = TRUE;
                            }
                      }
                }
              vend1 = (vendor_id_payload *)IsakmpFindPayload((generic_payload*)vend1, ISA_VEND_ID);
            }
        }
      // Q00959911 - End


      // We have the right payloads - cancel the retransmit timer.
      CancelTimer();
      // Is key exchange size wrong?
      // CD_AES ALERT !! test both sizes
      if ( ((ntohs(keyp->payload_len) - sizeof(key_x_payload)) != ourKeySize) &&
          ((ntohs(keyp->payload_len) - sizeof(key_x_payload)) != badKeySize) )
        return INVALID_KEY_INFO;

      // If signature mode, check for a cert request and ensure it
      // specifies the right cert type.
      if (saAuthMethod == RSA_SIG)
      {
        cert = (cert_payload *)IsakmpFindPayload(hdr, ISA_CERT_REQ);
        if (cert && (cert->cert_spec != 4))
          return BAD_CERT_REQ_SYNTAX;
      }

      // CD_AES : alert : we _should_ have parsed the VID by now...
      theirDHPublic = new UINT8[ourKeySize];
      if (!theirDHPublic)
      {
        delete this;
        return 0xFFFF;
      }

      bcopy((char *)keyp + sizeof(key_x_payload), (char *)theirDHPublic,
            ourKeySize);
      // If we are the responder, calculate our Diffie-Hellman values
      // and build our response message now.
      if (saIsakmpRole == RESPONDER)
      {
        if (ntohs(nonceI->payload_len) <= sizeof(nonce_payload))
          return PAYLOAD_MALFORMED;
        delete [] saMessage;
        saDH = new DHCls(saDHGroup, aesCompatOn);
        myDHPublic = new UINT8[ourKeySize];
        saMessageLength = sizeof(isakmp_hdr) + sizeof(key_x_payload)
                          + ourKeySize + sizeof(nonce_payload) + 20;
        if (saAuthMethod == RSA_SIG)
          saMessageLength += sizeofCertPayload;

        // Q00959911 - Begin
        // If we are doing DPD Exchange and DPD Vendor Id has not been
        // sent yet, we shall send it now
        // First we add to the message length
        if ( (!saDPDVendIdSent) && (saDPDExchange) )
          {
            saMessageLength += sizeof(vendor_id_payload) + 16;
          }
        // Q00959911 - End

        saMessage = new UINT8[saMessageLength];
        if (!saDH || !myDHPublic || !saMessage)
        {
          // We lose big time!
          delete this;
          return 0xFFFF;
        }

        // Set up the ISAKMP header...
        GetCookies((UINT32 *)saMessage);
        newhdr = (isakmp_hdr *)saMessage;
#ifdef LITTLE_ENDIAN
        *((UINT32 *)saMessage+4) = 0x00021004;
#else
        *((UINT32 *)saMessage+4) = 0x04100200;
#endif
        newhdr->mess_id = 0;
        newhdr->len = htonl(saMessageLength);
        // ...and the key exchange payload...
        // We need to save our public value internally.
        keyp = (key_x_payload *)(saMessage + sizeof(isakmp_hdr));
        keyp->next_payload = ISA_NONCE;
        keyp->reserved = 0;
        keyp->payload_len = htons(sizeof(key_x_payload)
                                  + saDH->PublicValueLength());
#ifdef LOAD_TEST
        semTake(ipsecTunnelTableSem, WAIT_FOREVER);
#endif
        if (FALSE == saDH->Setup(*isakmpRng, myDHPublic))
        {
          isakmpEventLog->Event(EventLog::HIGH,
                          "Error in Diffie-Hellman Setup, group=%u", (UINT32)saDHGroup);
          delete this;
          return 0xFFFF;
        }
#ifdef LOAD_TEST
        semGive(ipsecTunnelTableSem);
#endif
        bcopy((char *)myDHPublic, (char *)keyp + sizeof(key_x_payload),
              saDH->PublicValueLength());

        // ...and the nonce.
        nonceR = (nonce_payload *)((UINT8 *)keyp + sizeof(key_x_payload)
                                   + saDH->PublicValueLength());
        *((UINT16 *)nonceR) = 0;
        nonceR->payload_len = htons(sizeof(nonce_payload) + 20);
        isakmpRng->GetBlock((UINT8 *)nonceR + sizeof(nonce_payload), 20);

        if (saAuthMethod == RSA_SIG)
        {
          nonceR->next_payload = ISA_CERT_REQ;
          cert = (cert_payload *)((UINT8 *)nonceR+sizeof(nonce_payload)+20);
          *((UINT16 *)cert) = 0;
          cert->payload_len = htons(sizeofCertPayload);
          cert->cert_spec = 4;

          // Q00959911 - Begin
          // Add the Vendor Id payload after the Cert payload
          if ( (!saDPDVendIdSent) && (saDPDExchange) )
            {
              cert->next_payload = ISA_VEND_ID;
              vend1 = (vendor_id_payload *)((UINT8 *)cert + sizeofCertPayload);
              *((UINT16 *)vend1) = 0;
              vend1->payload_len = htons(sizeof(vendor_id_payload) + 16);
            }
          // Q00959911 - End
        }
        // Q00959911 - Begin
        else
          {
            // Add the Vendor Id payload after the Nonce payload
            if ( (!saDPDVendIdSent) && (saDPDExchange) )
              {
                nonceR->next_payload = ISA_VEND_ID;
                vend1 = (vendor_id_payload *)((UINT8 *)nonceR+sizeof(nonce_payload)+20);
                *((UINT16 *)vend1) = 0;
                vend1->payload_len = htons(sizeof(vendor_id_payload) + 16);
              }
          }

        // Fill in the values for the Vendor Id payload
        if ( (!saDPDVendIdSent) && (saDPDExchange) )
          {
#ifdef LITTLE_ENDIAN
            *((UINT32 *)vend1 + 1) = 0x13D7CAAF;        // DPD Vendor-id
            *((UINT32 *)vend1 + 2) = 0xC9F1A168;
            *((UINT32 *)vend1 + 3) = 0xFC96866B;
            *((UINT32 *)vend1 + 4) = 0x00015777;        // Major=01 Minor=00
#else
            *((UINT32 *)vend1 + 1) = 0xAFCAD713;        // DPD Vendor-id
            *((UINT32 *)vend1 + 2) = 0x68A1F1C9;
            *((UINT32 *)vend1 + 3) = 0x6B8696FC;
            *((UINT32 *)vend1 + 4) = 0x77570100;        // Major=01 Minor=00
#endif
            saDPDVendIdSent = TRUE;
          }
        // Q00959911 - End

      }
      // Otherwise, if we're the initiator, figure out the pointer to
      // our nonce in the current (old) transmission packet.
      else
      {
        nonceR = nonceI;
        nonceI = (nonce_payload *)(saMessage + sizeof(isakmp_hdr)
                                   + sizeof(key_x_payload)
                                   + saDH->PublicValueLength());
        if (ntohs(nonceR->payload_len) <= sizeof(nonce_payload))
          return PAYLOAD_MALFORMED;
      }
      // Do all those key material calculations...
      if (GenerateIsakmpKeys(nonceI, nonceR) == FALSE)
      {
        delete this;
        return 0xFFFF;
      }
      hashlen = (UINT16)prf->DigestSize();
      // Construct initiator's message.
      if (saIsakmpRole == INITIATOR)
      {
        delete [] saMessage;
        saMessage = 0;
        if (saAuthMethod == PRESHRD)
        {
          idLen = 4;
          idData = 0;
        }
        else
        {
          AlternateNameCls *altName = NULL;
          DnCls *serverDn = NULL;

          initiatorIdType = GetServerIdentity(saSession, saCESVersion, &serverDn, &altName, &idData, &idLen, &localError);
          //
          // If a supported id type is returned then we have a valid
          // server identity and certificate.  The type returned will
          // indicate if the serverDn or altName arg is set with the
          // actual identity info.
          //
          switch (initiatorIdType)
          {
            case ID_DER_ASN1_DN:
            if (serverDn != NULL)
            {
               // We already filled out idData in GetServerIdentity
               //localError = GetAsnFromDn(serverDn, &idData, &idLen);
            }
            else
            {
              idData = NULL;
              idLen = 0;
              localError = NO_SUBJECT_NAME;
            }
            break;

            case ID_IPV4_ADDR:
            case ID_USER_FQDN:
            case ID_FQDN:
            idData = NULL;
            idLen = 0;
            localError = ALTNAME_MISSING;
            //
            // Use our subject alternate name if we have one
            //
            if (altName != NULL)
            {
              char *altNameStr = (char *) (altName->GetAltNameStr());
              if (altNameStr != NULL)
              {
                if (initiatorIdType == ID_IPV4_ADDR)
                {
                    IpAddrCls serverAddr;

                    if ((localError = serverAddr.SetAscii(altNameStr)) == SUCCESS)
                    {
                      // TODO - check that serverAddr == saLocalAddr here?
                      idLen = 4;
                      idData = (UINT8 *) malloc(idLen);
                      if (idData != NULL)
                      {
                        *((UINT32 *) idData) = serverAddr;
                      }
                      else
                      {
                        idLen = 0;
                        localError = NO_MEMORY;
                      }
                    }
                }
                else
                {
                    idLen = strlen(altNameStr);
                    idData = (UINT8 *) malloc(idLen);
                    if (idData != NULL)
                    {
                        bcopy(altNameStr, (char *) idData, idLen);
                        localError = SUCCESS;
                    }
                    else
                    {
                        idLen = 0;
                        localError = NO_MEMORY;
                    }
                }
              }
            }
            break;

            default:
                 // localError is set by GetServerIdentity()
            break;
          }
          delete serverDn;
          delete altName;
        }

        if (localError != SUCCESS)
        {
            isakmpEventLog->Event(EventLog::PERSIST_HIGH,
                                  "Could not obtain local identity to send to %.*s, reason: %s",
                                  (UINT32)(EVENTLOGMAXTXT - 60),
                                  (UINT32)saRemoteIdString,
                                  (UINT32)errorCode.GetString(localError));
            if (saNewOakVersion)
              error = localError;
            delete this;
            return INVALID_KEY_INFO;
        }
        // If we have no existing ISAKMP SAs with the other side, send
        // an INITIAL-CONTACT Notify payload along with the rest of our
        // message.  This will inform the other side that it may clear
        // out any old SA state it may have.  (Specifically, it gets
        // around the problem of our boxes enforcing a "login limit"
        // of one when the other side reboots...)  If testSa exists
        // after this loop, then we DON'T send INITIAL-CONTACT.
        testSa = isakmpTable[IsadbHashFunction((UINT32)saLocalAddr,
                                               (UINT32)saRemoteAddr)];
        for (; testSa; testSa = testSa->nextSa)
        {
          if ((testSa != this) &&
              (testSa->saLocalAddr == saLocalAddr) &&
              (testSa->saRemoteAddr == saRemoteAddr) &&
              saSession && testSa->saSession &&
              (testSa->saSession->GetAccount() == saSession->GetAccount()))
            break;
        }
        // At first, we'll build this message as if it we were using
        // pre-shared keys.  We'll transmogrify it into the digital signature
        // format, if need be, in a little bit.  This allows us to pre-build
        // the ID payload and the hash we will sign in place.
        saMessageLength = sizeof(isakmp_hdr) + sizeof(id_payload) + idLen
          + sizeof(hash_payload) + hashlen;
        if (!testSa)
          saMessageLength += sizeof(notify_payload) + 16;
        saMessage = new UINT8[saMessageLength + MAX_PAD_SIZE];
        if (!saMessage)
        {
          /* svora: delete allocated memory */
          if(idData)
            {
              free(idData);
              idData=NULL;
            }

          // We lose big time!
          return 0xFFFF;
        }
        // Set up the ISAKMP header...
        GetCookies((UINT32 *)saMessage);
        newhdr = (isakmp_hdr *)saMessage;
#ifdef LITTLE_ENDIAN
        *((UINT32 *)saMessage+4) = 0x01021005;
#else
        *((UINT32 *)saMessage+4) = 0x05100201;
#endif
        newhdr->mess_id = 0;
        newhdr->len = htonl(saMessageLength);
        idp = (id_payload *)(saMessage + sizeof(isakmp_hdr));
        idp->reserved = 0;
        idp->payload_len = htons(sizeof(id_payload) + idLen);
        idp->protocol_id = 0;
        idp->port = 0;
        if (idData)
        {
          idp->id_type = initiatorIdType;
          bcopy((char *)idData, (char *)idp + sizeof(id_payload), idLen);
          free(idData);
          idData = NULL;
        }
        else
        {
          idp->id_type = ID_IPV4_ADDR;
          *((UINT32 *)idp + 2) = saLocalAddr;
        }
        idp->next_payload = ISA_HASH;
        hashp = (hash_payload *)((UINT8 *)idp + ntohs(idp->payload_len));
        *((UINT16 *)hashp) = 0;
        hashp->payload_len = htons(sizeof(hash_payload) + hashlen);
        prf->Update(myDHPublic, IKEDHCls::PublicValueLength(saDHGroup, aesCompatOn));
        prf->Update(theirDHPublic, IKEDHCls::PublicValueLength(saDHGroup, aesCompatOn));
        prf->Update((UINT8 *)saCookie, 16);
        prf->Update(initSaPayload, initSaPayloadLength);
        prf->Update((UINT8 *)idp + sizeof(generic_payload),
                    ntohs(idp->payload_len) - sizeof(generic_payload));
        prf->Final((UINT8 *)hashp + sizeof(hash_payload));
        if (saAuthMethod == RSA_SIG)
        {
          // Sign the data.
          if (!saSession || saSession->SignData(SEC_AUTHMETHOD_CERTIFICATE_RSA,
                                  (UINT8 *)hashp + sizeof(hash_payload),
                                  &sigData, &hashlen, &certData, &certLen,
                                  &localError) == FALSE)
          {
            if (saNewOakVersion)
              error = localError;
            delete this;
            return INVALID_KEY_INFO;
          }
          // Allocate a new message buffer, and rebuild...
          saMessageLength -= sizeof(hash_payload) + prf->DigestSize();
          saPreMessageLength = saMessageLength + sizeofCertPayload + certLen
            + sizeof(sig_payload) + hashlen;
          // If we're adding an INITIAL-CONTACT Notify, *don't* copy over
          // its length to the new message, since we haven't put it in yet!
          if (!testSa)
            saMessageLength -= sizeof(notify_payload) + 16;
          saPreMessage = new UINT8[saPreMessageLength + MAX_PAD_SIZE];
          if (!saPreMessage)
          {
            // We lose big time!
            return 0xFFFF;
          }
          newhdr->len = htonl(saPreMessageLength);
          idp->next_payload = ISA_CERT;
          bcopy((char *)saMessage, (char *)saPreMessage, saMessageLength);
          delete [] saMessage;
          saMessage = saPreMessage;
          cert = (cert_payload *)(saMessage + saMessageLength);
          saMessageLength = saPreMessageLength;
          saPreMessage = 0;
          saPreMessageLength = 0;
          cert->next_payload = ISA_SIG;
          cert->reserved = 0;
          cert->payload_len = htons(certLen + sizeofCertPayload);
          // Cert type is X.509 Certificate - Signature.
          cert->cert_spec = 4;
          bcopy((char *)certData, (char *)cert + sizeofCertPayload,
                certLen);
          hashp = (hash_payload *)((UINT8 *)cert + ntohs(cert->payload_len));
          *((UINT16 *)hashp) = 0;
          hashp->payload_len = htons(sizeof(sig_payload) + hashlen);
          bcopy((char *)sigData, (char *)hashp + sizeof(sig_payload),
                hashlen);
        }
        if (!testSa)
        {
          hashp->next_payload = ISA_NOTIFY;
          notify = (notify_payload *)
                   ((UINT8 *)hashp + ntohs(hashp->payload_len));
          *((UINT16 *)notify) = 0;
          notify->payload_len = htons(sizeof(notify_payload) + 16);
          notify->doi = IPSEC_DOI;
          notify->protocol_id = PROTO_ISAKMP;
          notify->spi_size = 16;
          notify->notify_message = INITIAL_CONTACT;
          GetCookies((UINT32 *)((UINT8 *)notify + sizeof(notify_payload)));
        }
      }
      // Reset state and retransmision timer, and we're done...
      saState = OAK_MM_KEY_AUTH;
      SetTimer(TIMER_RETRY, saIsakmpTimeout);
      break;

    case OAK_MM_KEY_AUTH:
      // Need to have ID and hash payloads.
      idp = (id_payload *)IsakmpFindPayload(hdr, ISA_ID);
      if (!idp)
        return 0xFFFF;

      if ((saAuthMethod == PRESHRD) && !IsakmpFindPayload(hdr, ISA_HASH))
        return 0xFFFF;

      // We have the right payloads... were they encrypted?
      if ((unsigned char)(hdr->flags & ISAKMP_HDR_ENCR_BIT) == 0)
        return 0xFFFF;
      // Cancel the retransmission timer now.
      CancelTimer();

      // Check out the ID...
      if ((idp->protocol_id && (idp->protocol_id != IPProtoUDP)) ||
          (idp->port && (idp->port != UDPPortISAKMP)) ||
          ((saAuthMethod == PRESHRD) && (idp->id_type != ID_IPV4_ADDR)))
      {
        *delSa = this;
        return INVALID_ID_INFO;
      }
      // Change state so that we don't respond prematurely.
      saState = OAK_AG_NOSTATE;
      // Save the message.
      delete [] saMessage;
      saMessageLength = ntohl(hdr->len);
      saMessage = new UINT8[saMessageLength];
      if (!saMessage)
      {
        localError = NO_MEMORY;
mainfail:
        if (saNewOakVersion)
          error = localError;
        *delSa = this;
        return isaError;
      }
      bcopy((char *)hdr, (char *)saMessage, saMessageLength);
      // Save the IV aside...  This is to cover the case where another
      // (perhaps rogue) message might come in while we're processing
      // async SessionCls calls.  If a rogue message did come in, the
      // act of decrypting it could cause us to lose the real encryptIV
      // value - unless we save it here.
      //!  *((UINT32 *)finalPhaseOneIV) = *((UINT32 *)encryptIV);
      //! *((UINT32 *)finalPhaseOneIV + 1) = *((UINT32 *)encryptIV + 1);
      CopyIV(finalPhaseOneIV, encryptIV);

      if (saAuthMethod == RSA_SIG)
      {
        cert = (cert_payload *)IsakmpFindPayload(hdr, ISA_CERT);
        // Currently, the cert must be X.509 Certificate - Signature;
        // anything else doesn't work.  CES "Version 3" (2.0) puts the
        // cert in as type 1 by mistake, so allow for that.
        //if (!cert || ((cert->cert_spec != 4) && (saCESVersion != 3) &&
        //      (saNewOakVersion != 3)))

        // Allow for pkcs7 and X509 Certificate signature certificate types
        if (!cert || ((cert->cert_spec != CERT_TYPE_PKCS7) &&
                      (cert->cert_spec != CERT_TYPE_X509CERTIFICATE_SIGNATURE)))
        {
          *delSa = this;
          return INVALID_CERT;
        }
        if (!IsakmpFindPayload(hdr, ISA_SIG))
        {
          *delSa = this;
          return INVALID_SIGNATURE;
        }
        cb = new IsakmpCallBackStr;
        if (!cb)
        {
          localError = NO_MEMORY;
          goto mainfail;
        }
        cb->cbSa = this;
        cb->cbSaCookie[0] = saCookie[0];
                cb->cbSaCookie[1] = saCookie[1];
                cb->cbSaCookie[2] = saCookie[2];
                cb->cbSaCookie[3] = saCookie[3];
        cb->cbIndex = IsadbHashFunction(saLocalAddr, saRemoteAddr);
        // Check the ID type, and do the right thing with it...
        switch (idp->id_type)
        {
          case ID_DER_ASN1_DN:
            idData = saMessage + ((UINT8 *)idp - (UINT8 *)hdr) +
                     sizeof(id_payload);
            idLen = ntohs(idp->payload_len) - sizeof(id_payload);
            uidType = SEC_UIDTYPE_ASN1_DN;
            break;

          case ID_IPV4_ADDR:
            // Make sure the ID used matches saRemoteAddr.
            if ((UINT32)saRemoteAddr !=
                *((UINT32 *)((UINT8 *)idp + sizeof(id_payload))))
            {
              delete cb;
              isaError = INVALID_ID_INFO;
              goto mainfail;
            }
            // Move saMessage aside, and build a new buffer to contain
            // the string form of the IP address.  We don't use saRemoteAddr
            // directly, since that could be deleted in mid-call.
            saPreMessage = saMessage;
            saMessage = new UINT8[17];
            if (!saMessage)
            {
              delete cb;
              localError = NO_MEMORY;
              goto mainfail;
            }
            saRemoteAddr.GetAscii((TEXT *)saMessage, 17);
            idData = saMessage;
            idLen = 17;
            uidType = SEC_UIDTYPE_IPADDR_AN;
            break;

          case ID_FQDN:
            saPreMessage = saMessage;
            idLen = ntohs(idp->payload_len) - sizeof(id_payload);
            saMessage = new UINT8[idLen+1];
            if (!saMessage)
            {
              delete cb;
              localError = NO_MEMORY;
              goto mainfail;
            }
            idData = saPreMessage + ((UINT8 *)idp - (UINT8 *)hdr) +
                     sizeof(id_payload);
            bcopy((char *) idData, (char *) saMessage, idLen);
            idData = saMessage;
            idData[idLen] = '\0';
            uidType = SEC_UIDTYPE_FQDN;
            break;

          case ID_USER_FQDN:
            saPreMessage = saMessage;
            idLen = ntohs(idp->payload_len) - sizeof(id_payload);
            saMessage = new UINT8[idLen+1];
            if (!saMessage)
            {
              delete cb;
              localError = NO_MEMORY;
              goto mainfail;
            }
            idData = saPreMessage + ((UINT8 *)idp - (UINT8 *)hdr) +
                     sizeof(id_payload);
            bcopy((char *) idData, (char *) saMessage, idLen);
            idData = saMessage;
            idData[idLen] = '\0';
            uidType = SEC_UIDTYPE_USER_FQDN;
            break;

          default:
            delete cb;
            isaError = INVALID_ID_INFO;
            goto mainfail;
        }
        cb->cbData = (void *)saMessage;
        // Lose the saMessage pointer, so that it doesn't get deleted while
        // the ValidateIdentity() call is underway.  We'll take care of it
        // properly when the async call returns, since it's saved in cbData.
        // Note that we feed saSession in here - if we're the initiator, it'll
        // be filled in; if we're the responder, it'll be zero.
        saMessage = 0;
        localError =
          SessionCls::ValidateIdentity(idData, idLen, uidType,
                                       SEC_TUNNELTYPE_IPSEC,
                                       MainValidateCallBack, (void *)cb,
                                       FALSE, NULL, saSession);
        if (localError != SUCCESS)
        {
          // Need to put saMessage back, so it gets deleted!
          saMessage = (UINT8 *)cb->cbData;
          delete cb;
          goto mainfail;
        }
        // To ensure that saSession survives even if this SA gets deleted
        // while ValidateIdentity() is in progress, we must add a reference
        // to it here, which will be deleted during callback one way or
        // the other.
        if (saSession)
          saSession->AddRef();
      }
      else
      {
        // Need to add a session reference here, too, since the following
        // function will remove it...
        if (saSession)
          saSession->AddRef();
        PostMainModeValidate(saSession, saMessage, 0, SUCCESS);
      }
      // fall through...

    default:
      return 0xFFFF;
  }

  return 0;
}
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[4]: [папа STL] Alexander Stepanov "Notes on Programming"
От: Константин Л. Франция  
Дата: 06.02.07 17:12
Оценка:
Здравствуйте, Шахтер, Вы писали:

[]

мда...вот это ужас
Re[6]: [папа STL] Alexander Stepanov "Notes on Programming"
От: Vain Россия google.ru
Дата: 06.02.07 17:15
Оценка:
Здравствуйте, Анатолий Широков, Вы писали:

А>>Да господа....

А>>Вам в Армию надо программировать.
АШ>Нет, просто наболело.
"Если сердишься, значит — не прав" (с) Путин
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re[3]: [папа STL] Alexander Stepanov "Notes on Programming"
От: creatman Германия  
Дата: 06.02.07 17:56
Оценка:
Здравствуйте, Константин Л., Вы писали:

КЛ>Здравствуйте, Шахтер, Вы писали:


КЛ>[]


КЛ>+1


КЛ>Но вот 20 строк не всегда получается. Имхо это иногда даже вредно.


Я встречал код где в каждом методе класса было не более чем 10 строчек, смотрелось очень элегантно, учитывая что методов порядка 30 было


Re[7]: [папа STL] Alexander Stepanov "Notes on Programming"
От: Константин Л. Франция  
Дата: 06.02.07 17:57
Оценка: :)
Здравствуйте, Vain, Вы писали:

V>Здравствуйте, Анатолий Широков, Вы писали:


А>>>Да господа....

А>>>Вам в Армию надо программировать.
АШ>>Нет, просто наболело.
V>"Если сердишься, значит — не прав" (с) Путин

вообще-то

"Ты сердишься Юпитер, значит ты неправ." (с) Прометей Зевсу.
Re[4]: [папа STL] Alexander Stepanov "Notes on Programming"
От: Константин Л. Франция  
Дата: 06.02.07 18:00
Оценка:
Здравствуйте, creatman, Вы писали:

C>Здравствуйте, Константин Л., Вы писали:


КЛ>>Здравствуйте, Шахтер, Вы писали:


КЛ>>[]


КЛ>>+1


КЛ>>Но вот 20 строк не всегда получается. Имхо это иногда даже вредно.


C>Я встречал код где в каждом методе класса было не более чем 10 строчек, смотрелось очень элегантно, учитывая что методов порядка 30 было


это все понятно. Просто надо знать меру. Если стоит выбор м/у написанием 2 методов на 20 строк каждый, которые принимают по 10 параметров, я напишу 1, кот принимает 5 параметров. Если он конечно останется тамким же general, как те 2.
Re[4]: То есть они уже разорились?
От: Erop Россия  
Дата: 06.02.07 19:28
Оценка: +1
Здравствуйте, Аноним, Вы писали:

А>>Т.е. проблема не в правилах, а в дисциплине их применения.


А>И тем не менее, постоянно плодятся горы говно-кода. Знаю о некоем проекте. Кошмар страшенный, кода — уже за миллион(ы?) строк перевалило. Считают себя немерянными профессионалами, на уровне незыблемых истин — запрет использования СТЛ (дада, они до сих пор уверены, что компиляторы С++ — плохие и с шаблонами все плохо),..


А что с продуктом? Качество-то хорошее? Развите идёт? Поддержка там, нове версии...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[5]: объект-механизм
От: Erop Россия  
Дата: 06.02.07 19:34
Оценка: +1
Здравствуйте, Константин Л., Вы писали:

КЛ>это все понятно. Просто надо знать меру. Если стоит выбор м/у написанием 2 методов на 20 строк каждый, которые принимают по 10 параметров, я напишу 1, кот принимает 5 параметров. Если он конечно останется тамким же general, как те 2.


Я, в таких случаях, обычно пишу объект-механизм
Автор: Erop
Дата: 12.01.07
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[6]: объект-механизм
От: Константин Л. Франция  
Дата: 06.02.07 20:26
Оценка: +1
Здравствуйте, Erop, Вы писали:

[]

E>Я, в таких случаях, обычно пишу объект-механизм
Автор: Erop
Дата: 12.01.07


угу, я тоже бывает
Re[5]: [папа STL] Alexander Stepanov "Notes on Programming"
От: Privalov  
Дата: 07.02.07 06:13
Оценка:
Здравствуйте, Константин Л., Вы писали:

КЛ>мда...вот это ужас


Это еще не самый худший вариант. Все goto в одну точку показывают, условной компиляции почти нет...

Простите, не удержался. Иногда с подобными ужасами приходится сталкиваться. Причем речь идет о системах, работающих в режимш 24 — 7.
Re[6]: [папа STL] Alexander Stepanov "Notes on Programming"
От: Lorenzo_LAMAS  
Дата: 07.02.07 07:49
Оценка:
АШ>Нет, просто наболело.

Of course, the code must be complete enough to compile and link.
Re[6]: [папа STL] Alexander Stepanov "Notes on Programming"
От: Lorenzo_LAMAS  
Дата: 07.02.07 07:53
Оценка:
P>Это еще не самый худший вариант. Все goto в одну точку показывают, условной компиляции почти нет...

P>Простите, не удержался. Иногда с подобными ужасами приходится сталкиваться. Причем речь идет о системах, работающих в режимш 24 — 7.


Мне вот приходилось иметь дело с кодом, транслированным напрямую из фортрана. Там (в этом коде, а не в программах на фортране вообще) стандарт — функции по 5000 строк, с чудовищно хитрыми ветвлениями, циклами и тучей goto (разбросанным по всем этим 5000 строк). Вижуал при попытке скомпилировать и соптимизировать это чудо становится раком Этакий стресс-тест для компиляторов
Of course, the code must be complete enough to compile and link.
Re[7]: [папа STL] Alexander Stepanov "Notes on Programming"
От: Privalov  
Дата: 07.02.07 08:04
Оценка:
Здравствуйте, Lorenzo_LAMAS, Вы писали:

L_L>Мне вот приходилось иметь дело с кодом, транслированным напрямую из фортрана. Там (в этом коде, а не в программах на фортране вообще) стандарт — функции по 5000 строк, с чудовищно хитрыми ветвлениями, циклами и тучей goto (разбросанным по всем этим 5000 строк). Вижуал при попытке скомпилировать и соптимизировать это чудо становится раком Этакий стресс-тест для компиляторов


Ну как же, как же... Еще даже транслятор был лет 10 назад — forc назывался или как-то так. Пробовали мы его. После нескольких попыток (с ним и без него) переписать Фортрановский код на С, пришли к выводу, что лучше оставить код на Фортране как есть. Легче оказалось прикрутить Сишные функции к Фортрану (в среде MS DOS, MSC 6.0, MS Fortran 5.0). Решение оказалось прпроческим — переход с MS DOS на Windows прошел практически незаметно.
Re[8]: [папа STL] Alexander Stepanov "Notes on Programming"
От: Lorenzo_LAMAS  
Дата: 07.02.07 08:31
Оценка:
P>Ну как же, как же... Еще даже транслятор был лет 10 назад — forc назывался или как-то так. Пробовали мы его. После нескольких попыток (с ним и без него) переписать Фортрановский код на С, пришли к выводу, что лучше оставить код на Фортране как есть. Легче оказалось прикрутить Сишные функции к Фортрану (в среде MS DOS, MSC 6.0, MS Fortran 5.0). Решение оказалось прпроческим — переход с MS DOS на Windows прошел практически незаметно.

ИМХО:

Переписывать такой код — это вообще занятие не для слабонервных. В описанном мною случае исходный код на фортране существовал много лет, был он основательно "отстоявшимся" во всех понятиях этого слова Т.е. лучше его не трогать, вроде работает, а разобраться как или найти ошибку в нем — уже довольно сложно. Лично для меня просто нереально — что там за алгоритм исходный был, как его десятилетиями все кому не лень модифицировали и почему — уже не узнать в этом хитром переплетении ифов-циклов-неочевидных-готу-в-любую-точку в этих 5000 и более строк. Проще взять и заново все написать. Но зачем, если уже есть работающее решение?
Те люди на С++ переходили в 95-96 году, решили пользоваться ООП, мол старый код уже невозможно было нормально дальше развивать и поддерживать из-за его размеров — типа тут-то С++ и ООП им должен был помочь. Но блин, как же они помогут, если взять утилиту f2c и все это старое барахло банально перетащить в новый код, слегка поменяв лишь синтаксис?
Другое дело, что если оставить фортранный код, то одновременно нужен и компилятор фортрана, и С++.
Of course, the code must be complete enough to compile and link.
Re[5]: То есть они уже разорились?
От: Аноним  
Дата: 07.02.07 08:38
Оценка:
E>А что с продуктом? Качество-то хорошее? Развите идёт? Поддержка там, нове версии...

Странно, что ты про качество спрашиваешь. Ты сообщение мое читал? Вот это вот:

"Все течет, падает, жрет память гигами, работает медленно, как будто на жаве или питоне писали. "


о качестве не говорит?

Развитие — да идет, этакий регресс — убожище их становится все хуже и хуже. Естественно, выходят новые версии.
.
Re[6]: То есть они уже разорились?
От: bkat  
Дата: 07.02.07 09:18
Оценка: +1
Здравствуйте, Аноним, Вы писали:

E>>А что с продуктом? Качество-то хорошее? Развите идёт? Поддержка там, нове версии...


А>Странно, что ты про качество спрашиваешь. Ты сообщение мое читал? Вот это вот:


А>

А>"Все течет, падает, жрет память гигами, работает медленно, как будто на жаве или питоне писали. "


А>о качестве не говорит?


А>Развитие — да идет, этакий регресс — убожище их становится все хуже и хуже. Естественно, выходят новые версии.

А>.

И судя по всему, ты в этом принимаешь активное участие
Re[7]: То есть они уже разорились?
От: Аноним  
Дата: 07.02.07 09:46
Оценка:
B>И судя по всему, ты в этом принимаешь активное участие

Не пояснишь, с чего ты это взял? Что и как у них я знаю, так как вынужден был пользоваться их "продуктом".
Re[4]: [папа STL] Alexander Stepanov "Notes on Programming"
От: MasterZiv СССР  
Дата: 07.02.07 10:16
Оценка: :))) :)
Шахтер пишет:

> Разумеется, следование данному правилу (как и остальным) нельзя доводить

> до абсурда.
> Но писать вот такие функции...

> unsigned short

> IsakmpSaCls::ProcessMainMode(isakmp_hdr *hdr, IsakmpSaCls **delSa,
> ERROR_CODE &error)
> {

Спасибо, Шахтер, очень обнадеживающий пост.
Обнадеживает то, что ты не один такой (в смысле меня
обнадеживает , что я не один такой на свете),
что тебя понимают, что есть люди которые думают так же как ты...

Только у нас код хуже ...
Posted via RSDN NNTP Server 2.0
Re[8]: То есть они уже разорились?
От: bkat  
Дата: 07.02.07 10:34
Оценка:
Здравствуйте, Аноним, Вы писали:

B>>И судя по всему, ты в этом принимаешь активное участие


А>Не пояснишь, с чего ты это взял? Что и как у них я знаю, так как вынужден был пользоваться их "продуктом".


Просто предположил.
Для простого пользователя ты знаешь слишком много подробностей
типа того что они "недавно решили использовать ворнинг -Weff++"...

Но если это не так, то уж прости...
Ничего плохого не имел ввиду.
На практике много с чем приходится сталкиваться
и далеко не всегда есть возможность как-то повлиять на ситуацию...
Re[9]: То есть они уже разорились?
От: Аноним  
Дата: 07.02.07 10:44
Оценка:
Здравствуйте, bkat, Вы писали:

B>Здравствуйте, Аноним, Вы писали:


B>>>И судя по всему, ты в этом принимаешь активное участие


А>>Не пояснишь, с чего ты это взял? Что и как у них я знаю, так как вынужден был пользоваться их "продуктом".


B>Просто предположил.

B>Для простого пользователя ты знаешь слишком много подробностей
B>типа того что они "недавно решили использовать ворнинг -Weff++"...

Код доступен в исходниках — потому знаю про то, что внутри (приходилось и с ними знакомиться).
Так же регулярно читал что пишут в их форум. Про -Weff++ — это просто, начиная с некоторой версии поперли горы ворнингов. Потом они пропали и появился код, их давящий, но не меняющий сути дела

B>Но если это не так, то уж прости...

B>Ничего плохого не имел ввиду.

Ок.

B>На практике много с чем приходится сталкиваться

B>и далеко не всегда есть возможность как-то повлиять на ситуацию...

Возможности повлиять в моем случае — нет.
А вообще я развел флейм просто потому, что как сказал Анатолий Широков — наболело
Но все, заканчиваю с нытьем, к тому же — оффтоп
Re[9]: [папа STL] Alexander Stepanov "Notes on Programming"
От: Privalov  
Дата: 07.02.07 11:12
Оценка: +1
Здравствуйте, Lorenzo_LAMAS, Вы писали:

L_L>ИМХО:


L_L>Переписывать такой код — это вообще занятие не для слабонервных. В описанном мною случае исходный код на фортране существовал много лет, был он основательно "отстоявшимся" во всех понятиях этого слова


Аналогично. Фортрановский код писался в течение полутора десятков лет, начиналось все на чем-то типа ЕС-1020.

L_L>Т.е. лучше его не трогать, вроде работает, а разобраться как или найти ошибку в нем — уже довольно сложно. Лично для меня просто нереально — что там за алгоритм исходный был, как его десятилетиями все кому не лень модифицировали и почему — уже не узнать в этом хитром переплетении ифов-циклов-неочевидных-готу-в-любую-точку в этих 5000 и более строк. Проще взять и заново все написать. Но зачем, если уже есть работающее решение?


По исходникам на Фортране узнать, что за алгоритм используется, можно только если в коде присутствуют комментарии, содержащие ссылки на соответствующие статьи и/или монографии. Однако, кто будет набивать это на перфокартах?

На С переписали только некоторые вещи: что-то низкоуровневое, сортировку поменяли с пузырька на быструю (там после каждой итерации увесистый массив получался, который сортировать требовалось), графики построили. А основной код как работал, так и работает (по слухам, до сих пор) на Фортране.

L_L>Те люди на С++ переходили в 95-96 году, решили пользоваться ООП, мол старый код уже невозможно было нормально дальше развивать и поддерживать из-за его размеров — типа тут-то С++ и ООП им должен был помочь.


Об ООП они не слишком лестно отзывались — "докторскую кто-то сделал себе".

L_L>..Но блин, как же они помогут, если взять утилиту f2c и все это старое барахло банально перетащить в новый код, слегка поменяв лишь синтаксис?


Делать продукт из того кода не планировалось. Все это хозяйство писалось математиками для их собственных нужд. Я им только немного помог. f2c мы пробовали, но нам показалось, что он создает проблем больше, чем решает. Поэтому Фортрановский код, проверенный временем , и оставили.

L_L>Другое дело, что если оставить фортранный код, то одновременно нужен и компилятор фортрана, и С++.


MS Fortran и MS C были отлично совместимы друг с другом. Я только написал несколько h-файлов для С и несколько подпрограмм interface для Фортрана. Проект собирался nmake-ом.
Re[6]: То есть они уже разорились?
От: Erop Россия  
Дата: 07.02.07 12:07
Оценка:
Здравствуйте, Аноним, Вы писали:

А>

А>"Все течет, падает, жрет память гигами, работает медленно, как будто на жаве или питоне писали. "

А>о качестве не говорит?
А>Развитие — да идет, этакий регресс — убожище их становится все хуже и хуже. Естественно, выходят новые версии.

Ну мало ли что там и как. Знаешь анекдот про мышек т кактус?
В целом это дело, я так понял покупают? Или это какой-то oprn source?
А>.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[7]: про код генерируемый автоматически
От: Erop Россия  
Дата: 07.02.07 12:09
Оценка:
Здравствуйте, Lorenzo_LAMAS, Вы писали:

L_L>Мне вот приходилось иметь дело с кодом, транслированным напрямую из фортрана. Там (в этом коде, а не в программах на фортране вообще) стандарт — функции по 5000 строк, с чудовищно хитрыми ветвлениями, циклами и тучей goto (разбросанным по всем этим 5000 строк). Вижуал при попытке скомпилировать и соптимизировать это чудо становится раком Этакий стресс-тест для компиляторов


Мой опыт, подсказывает мне, что очень трудно породить код автоматически так, чтобы он не стал стресс-тестом для компиляторов
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[8]: FORTRAN рулит!!!
От: Erop Россия  
Дата: 07.02.07 12:11
Оценка: +1 -1
Здравствуйте, Privalov, Вы писали:

P>Ну как же, как же... Еще даже транслятор был лет 10 назад — forc назывался или как-то так. Пробовали мы его. После нескольких попыток (с ним и без него) переписать Фортрановский код на С, пришли к выводу, что лучше оставить код на Фортране как есть. Легче оказалось прикрутить Сишные функции к Фортрану (в среде MS DOS, MSC 6.0, MS Fortran 5.0). Решение оказалось прпроческим — переход с MS DOS на Windows прошел практически незаметно.


ИМХО, в области вычматов FORTRAN по переносимости далеко впереди планеты всей. Давно и надолго
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: [папа STL] Alexander Stepanov "Notes on Programming"
От: Smooky Россия  
Дата: 07.02.07 12:37
Оценка: :))
Здравствуйте, Шахтер, Вы писали:

Ш>Здравствуйте, Константин Л., Вы писали:


КЛ>>Здравствуйте, Шахтер, Вы писали:


КЛ>>[]


КЛ>>+1


КЛ>>Но вот 20 строк не всегда получается. Имхо это иногда даже вредно.


Ш>Разумеется, следование данному правилу (как и остальным) нельзя доводить до абсурда.

Ш>Но писать вот такие функции...


Ш>
Ш>unsigned short
Ш>IsakmpSaCls::ProcessMainMode(isakmp_hdr *hdr, IsakmpSaCls **delSa,
Ш>                             ERROR_CODE &error)
Ш>


Нормальная функция, у нас во всех всём проекте такие... Привык уже наверное... И это еще в принципе всё понятно что написано...
Только Путин, и никого кроме Путина! О Великий и Могучий Путин — царь на веки веков, навсегда!
Смотрю только Соловьева и Михеева, для меня это самые авторитетные эксперты.
КРЫМ НАШ! СКОРО И ВСЯ УКРАИНА БУДЕТ НАШЕЙ!
Re[7]: То есть они уже разорились?
От: Аноним  
Дата: 07.02.07 12:45
Оценка:
E>Ну мало ли что там и как. Знаешь анекдот про мышек т кактус?
E>В целом это дело, я так понял покупают? Или это какой-то oprn source?
А>>.

+1 за анекдот. 100% попадание
И да, это опен сорс. По определенным причинам — альтернатив нет.
Re[8]: То есть они уже разорились?
От: Erop Россия  
Дата: 07.02.07 12:55
Оценка:
Здравствуйте, Аноним, Вы писали:

А>+1 за анекдот. 100% попадание

Для +1 там кнопочка справа вверху есть

А>И да, это опен сорс. По определенным причинам — альтернатив нет.

Вот блин удивил! Ещё один через одно местно написаный опенсорс
Ещё не известно чего бы там было, если бы они STL привинтили...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[9]: FORTRAN рулит!!!
От: Lorenzo_LAMAS  
Дата: 07.02.07 13:44
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, Privalov, Вы писали:


P>>Ну как же, как же... Еще даже транслятор был лет 10 назад — forc назывался или как-то так. Пробовали мы его. После нескольких попыток (с ним и без него) переписать Фортрановский код на С, пришли к выводу, что лучше оставить код на Фортране как есть. Легче оказалось прикрутить Сишные функции к Фортрану (в среде MS DOS, MSC 6.0, MS Fortran 5.0). Решение оказалось прпроческим — переход с MS DOS на Windows прошел практически незаметно.


E>ИМХО, в области вычматов FORTRAN по переносимости далеко впереди планеты всей. Давно и надолго


А у меня наивный вопрос — вот я говорил о том, как вижуал пыхтит минут по 5-10 над файлом из 7 тысяч строк, компилируя-оптимизируя кошмарик, полученный после f2c. Этот код — почти транслитерация. Интересно — фортрановский компилятор быстро его скомпилит-соптимизирует? И насколько хорошо? Я понимаю, что это зависит от... Нету компилятора фортрана, чтобы попробовать (кстати нету уже и исходного варианта на фортране).
Of course, the code must be complete enough to compile and link.
Re[8]: про код генерируемый автоматически
От: Lorenzo_LAMAS  
Дата: 07.02.07 13:47
Оценка:
E>Мой опыт, подсказывает мне, что очень трудно породить код автоматически так, чтобы он не стал стресс-тестом для компиляторов

Я думаю, это почти транслитерация.
Of course, the code must be complete enough to compile and link.
Re[10]: FORTRAN рулит!!!
От: Erop Россия  
Дата: 07.02.07 14:15
Оценка: 4 (1)
Здравствуйте, Lorenzo_LAMAS, Вы писали:

L_L>А у меня наивный вопрос — вот я говорил о том, как вижуал пыхтит минут по 5-10 над файлом из 7 тысяч строк, компилируя-оптимизируя кошмарик, полученный после f2c. Этот код — почти транслитерация. Интересно — фортрановский компилятор быстро его скомпилит-соптимизирует? И насколько хорошо? Я понимаю, что это зависит от... Нету компилятора фортрана, чтобы попробовать (кстати нету уже и исходного варианта на фортране).


И быстро и хорошо. FORTRAN -- это очень отлаженная именно на таких программах штука. И как раз с упором на оптимизацию

Типичное использование FORTRAN, в течении многих лет такое:

1) Ты пишешь и отлаживаешь свою прогу на каком-то дешёвом компе скока хочешь
2) Реальный прогон н ареальном объёме данных делаешь на супер-дорогом, но ещё более супер-производительном супер-компьютере

Как ты понимаешь в таких условиях оптимизауия и переносимость очень критичны
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[9]: про код генерируемый автоматически
От: Erop Россия  
Дата: 07.02.07 14:17
Оценка:
Здравствуйте, Lorenzo_LAMAS, Вы писали:

L_L>Я думаю, это почти транслитерация.


И что? Вообще-то я всегда воспринимал С(K&R) как "более близкую к архитектуре ЭВМ" версию FORTRAN
Они правда довольно похожи.

Но даже этой "почти транслитирации" хватает, чтобы поставить всё раком.

просто на C++ люди и автоматы пишут очень по разному
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: [папа STL] Alexander Stepanov "Notes on Programming"
От: Аноним  
Дата: 07.02.07 17:55
Оценка: :)
Здравствуйте, Шахтер, Вы писали:

Не знаю какие строки в STL писал сам Степанов(или он архитектил ее?), но если посмотреть в исходники STL то они не особо вписываются в этот набор правил.

P.S. И везде там подписи Copyright (c) 1992-2005 by P.J. Plauger.
Re[3]: [папа STL] Alexander Stepanov "Notes on Programming"
От: Erop Россия  
Дата: 07.02.07 18:04
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Не знаю какие строки в STL писал сам Степанов(или он архитектил ее?), но если посмотреть в исходники STL то они не особо вписываются в этот набор правил.


А>P.S. И везде там подписи Copyright (c) 1992-2005 by P.J. Plauger.



У STL вейчас есть вагон реализаций с разными авторами и подходами.
Хотя, ИМХО, и степановское чудовище образцом читабельности назвать трудно

А Степанов был среди тех, кто эту вот концепцию хитрых шаблонов придумал
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[5]: [папа STL] Alexander Stepanov "Notes on Programming"
От: Privalov  
Дата: 08.02.07 05:45
Оценка:
Здравствуйте, Smooky, Вы писали:

Ш>>
Ш>>unsigned short
Ш>>IsakmpSaCls::ProcessMainMode(isakmp_hdr *hdr, IsakmpSaCls **delSa,
Ш>>                             ERROR_CODE &error)
Ш>>


S>Нормальная функция, у нас во всех всём проекте такие... Привык уже наверное... И это еще в принципе всё понятно что написано...


В той функции для полного счастья мелочи не хватает — надо все локальные переменные наружу вытащить, ну и вместо передачи параметров глобальные переменные применить.
Re[9]: FORTRAN рулит!!!
От: Privalov  
Дата: 08.02.07 05:51
Оценка:
Здравствуйте, Erop, Вы писали:

E>ИМХО, в области вычматов FORTRAN по переносимости далеко впереди планеты всей. Давно и надолго


При переносе Фортрановской программы в MS DOS с ЕС ЭВМ я подправил что-то в операторах READ / WRITE и объявил один длинный массив HUGE. В остальной код в это время я даже не заглядывал.
Re[4]: Исходники Perl...
От: SergeCpp Россия http://zoozahita.ru
Дата: 08.02.07 08:54
Оценка: :)
Здравствуйте, Шахтер!

Ш>Но писать вот такие функции...


Вспомнилось... Занимался я как-то извлечением механизма обработки регулярных выражений из Perl'а...

Увидел исходники...

Брался несколько раз и откладывал...

Потом как-то набрался мужества и осилил

Столько там встретил интересного

В общем, считай, заново переписал

Ужас — одно слово. Просто — ужас.

Вот сейчас скачал версию 5.8.8 stable

Полюбуйтесь на файл regcomp.c
http://zoozahita.ruБездомные животные Екатеринбурга ищут хозяев
Re[5]: Исходники Perl...
От: SergeCpp Россия http://zoozahita.ru
Дата: 08.02.07 09:31
Оценка: :))
Кстати, не удержусь...

Вот функция, имеющая отношение к оптимизации регулярного выражения...

Ровно 1000 строк!

Ну, чуть больше, просто в SciTE сейчас смотрю, свернул её "плюсиком",
открывающая скобка на 674 строке, а следующая за свёрнутым блоком строка — 1674

Модераторы — не удаляйте... Пусть Ларри Уоллу будет стыдно

/* REx optimizer.  Converts nodes into quickier variants "in place".
   Finds fixed substrings.  */

/* Stops at toplevel WHILEM as well as at "last". At end *scanp is set
   to the position after last scanned or to NULL. */

STATIC I32
S_study_chunk(pTHX_ RExC_state_t *pRExC_state, regnode **scanp, I32 *deltap, regnode *last, scan_data_t *data, U32 flags)
            /* scanp: Start here (read-write). */
            /* deltap: Write maxlen-minlen here. */
            /* last: Stop before this one. */
{
    I32 min = 0, pars = 0, code;
    regnode *scan = *scanp, *next;
    I32 delta = 0;
    int is_inf = (flags & SCF_DO_SUBSTR) && (data->flags & SF_IS_INF);
    int is_inf_internal = 0;        /* The studied chunk is infinite */
    I32 is_par = OP(scan) == OPEN ? ARG(scan) : 0;
    scan_data_t data_fake;
    struct regnode_charclass_class and_with; /* Valid if flags & SCF_DO_STCLASS_OR */

    while (scan && OP(scan) != END && scan < last) {
    /* Peephole optimizer: */

    if (PL_regkind[(U8)OP(scan)] == EXACT) {
        /* Merge several consecutive EXACTish nodes into one. */
        regnode *n = regnext(scan);
        U32 stringok = 1;
#ifdef DEBUGGING
        regnode *stop = scan;
#endif

        next = scan + NODE_SZ_STR(scan);
        /* Skip NOTHING, merge EXACT*. */
        while (n &&
           ( PL_regkind[(U8)OP(n)] == NOTHING ||
             (stringok && (OP(n) == OP(scan))))
           && NEXT_OFF(n)
           && NEXT_OFF(scan) + NEXT_OFF(n) < I16_MAX) {
        if (OP(n) == TAIL || n > next)
            stringok = 0;
        if (PL_regkind[(U8)OP(n)] == NOTHING) {
            NEXT_OFF(scan) += NEXT_OFF(n);
            next = n + NODE_STEP_REGNODE;
#ifdef DEBUGGING
            if (stringok)
            stop = n;
#endif
            n = regnext(n);
        }
        else if (stringok) {
            const int oldl = STR_LEN(scan);
            regnode *nnext = regnext(n);

            if (oldl + STR_LEN(n) > U8_MAX)
            break;
            NEXT_OFF(scan) += NEXT_OFF(n);
            STR_LEN(scan) += STR_LEN(n);
            next = n + NODE_SZ_STR(n);
            /* Now we can overwrite *n : */
            Move(STRING(n), STRING(scan) + oldl, STR_LEN(n), char);
#ifdef DEBUGGING
            stop = next - 1;
#endif
            n = nnext;
        }
        }

        if (UTF && OP(scan) == EXACTF && STR_LEN(scan) >= 6) {
/*
  Two problematic code points in Unicode casefolding of EXACT nodes:

   U+0390 - GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS
   U+03B0 - GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS

   which casefold to

   Unicode            UTF-8

   U+03B9 U+0308 U+0301        0xCE 0xB9 0xCC 0x88 0xCC 0x81
   U+03C5 U+0308 U+0301        0xCF 0x85 0xCC 0x88 0xCC 0x81

   This means that in case-insensitive matching (or "loose matching",
   as Unicode calls it), an EXACTF of length six (the UTF-8 encoded byte
   length of the above casefolded versions) can match a target string
   of length two (the byte length of UTF-8 encoded U+0390 or U+03B0).
   This would rather mess up the minimum length computation.

   What we'll do is to look for the tail four bytes, and then peek
   at the preceding two bytes to see whether we need to decrease
   the minimum length by four (six minus two).

   Thanks to the design of UTF-8, there cannot be false matches:
   A sequence of valid UTF-8 bytes cannot be a subsequence of
   another valid sequence of UTF-8 bytes.

*/
         char *s0 = STRING(scan), *s, *t;
         char *s1 = s0 + STR_LEN(scan) - 1, *s2 = s1 - 4;
         const char * const t0 = "\xcc\x88\xcc\x81";
         const char * const t1 = t0 + 3;

         for (s = s0 + 2;
              s < s2 && (t = ninstr(s, s1, t0, t1));
              s = t + 4) {
              if (((U8)t[-1] == 0xB9 && (U8)t[-2] == 0xCE) ||
              ((U8)t[-1] == 0x85 && (U8)t[-2] == 0xCF))
               min -= 4;
         }
        }

#ifdef DEBUGGING
        /* Allow dumping */
        n = scan + NODE_SZ_STR(scan);
        while (n <= stop) {
        if (PL_regkind[(U8)OP(n)] != NOTHING || OP(n) == NOTHING) {
            OP(n) = OPTIMIZED;
            NEXT_OFF(n) = 0;
        }
        n++;
        }
#endif
    }
    /* Follow the next-chain of the current node and optimize
       away all the NOTHINGs from it.  */
    if (OP(scan) != CURLYX) {
        const int max = (reg_off_by_arg[OP(scan)]
               ? I32_MAX
               /* I32 may be smaller than U16 on CRAYs! */
               : (I32_MAX < U16_MAX ? I32_MAX : U16_MAX));
        int off = (reg_off_by_arg[OP(scan)] ? ARG(scan) : NEXT_OFF(scan));
        int noff;
        regnode *n = scan;
    
        /* Skip NOTHING and LONGJMP. */
        while ((n = regnext(n))
           && ((PL_regkind[(U8)OP(n)] == NOTHING && (noff = NEXT_OFF(n)))
               || ((OP(n) == LONGJMP) && (noff = ARG(n))))
           && off + noff < max)
        off += noff;
        if (reg_off_by_arg[OP(scan)])
        ARG(scan) = off;
        else
        NEXT_OFF(scan) = off;
    }
    /* The principal pseudo-switch.  Cannot be a switch, since we
       look into several different things.  */
    if (OP(scan) == BRANCH || OP(scan) == BRANCHJ
           || OP(scan) == IFTHEN || OP(scan) == SUSPEND) {
        next = regnext(scan);
        code = OP(scan);
    
        if (OP(next) == code || code == IFTHEN || code == SUSPEND) {
        I32 max1 = 0, min1 = I32_MAX, num = 0;
        struct regnode_charclass_class accum;
        
        if (flags & SCF_DO_SUBSTR) /* XXXX Add !SUSPEND? */
            scan_commit(pRExC_state, data); /* Cannot merge strings after this. */
        if (flags & SCF_DO_STCLASS)
            cl_init_zero(pRExC_state, &accum);
        while (OP(scan) == code) {
            I32 deltanext, minnext, f = 0, fake;
            struct regnode_charclass_class this_class;

            num++;
            data_fake.flags = 0;
            if (data) {        
            data_fake.whilem_c = data->whilem_c;
            data_fake.last_closep = data->last_closep;
            }
            else
            data_fake.last_closep = &fake;
            next = regnext(scan);
            scan = NEXTOPER(scan);
            if (code != BRANCH)
            scan = NEXTOPER(scan);
            if (flags & SCF_DO_STCLASS) {
            cl_init(pRExC_state, &this_class);
            data_fake.start_class = &this_class;
            f = SCF_DO_STCLASS_AND;
            }        
            if (flags & SCF_WHILEM_VISITED_POS)
            f |= SCF_WHILEM_VISITED_POS;
            /* we suppose the run is continuous, last=next...*/
            minnext = study_chunk(pRExC_state, &scan, &deltanext,
                      next, &data_fake, f);
            if (min1 > minnext)
            min1 = minnext;
            if (max1 < minnext + deltanext)
            max1 = minnext + deltanext;
            if (deltanext == I32_MAX)
            is_inf = is_inf_internal = 1;
            scan = next;
            if (data_fake.flags & (SF_HAS_PAR|SF_IN_PAR))
            pars++;
            if (data && (data_fake.flags & SF_HAS_EVAL))
            data->flags |= SF_HAS_EVAL;
            if (data)
            data->whilem_c = data_fake.whilem_c;
            if (flags & SCF_DO_STCLASS)
            cl_or(pRExC_state, &accum, &this_class);
            if (code == SUSPEND)
            break;
        }
        if (code == IFTHEN && num < 2) /* Empty ELSE branch */
            min1 = 0;
        if (flags & SCF_DO_SUBSTR) {
            data->pos_min += min1;
            data->pos_delta += max1 - min1;
            if (max1 != min1 || is_inf)
            data->longest = &(data->longest_float);
        }
        min += min1;
        delta += max1 - min1;
        if (flags & SCF_DO_STCLASS_OR) {
            cl_or(pRExC_state, data->start_class, &accum);
            if (min1) {
            cl_and(data->start_class, &and_with);
            flags &= ~SCF_DO_STCLASS;
            }
        }
        else if (flags & SCF_DO_STCLASS_AND) {
            if (min1) {
            cl_and(data->start_class, &accum);
            flags &= ~SCF_DO_STCLASS;
            }
            else {
            /* Switch to OR mode: cache the old value of
             * data->start_class */
            StructCopy(data->start_class, &and_with,
                   struct regnode_charclass_class);
            flags &= ~SCF_DO_STCLASS_AND;
            StructCopy(&accum, data->start_class,
                   struct regnode_charclass_class);
            flags |= SCF_DO_STCLASS_OR;
            data->start_class->flags |= ANYOF_EOS;
            }
        }

        }
        else if (code == BRANCHJ)    /* single branch is optimized. */
        scan = NEXTOPER(NEXTOPER(scan));
        else            /* single branch is optimized. */
        scan = NEXTOPER(scan);
        continue;
    }
    else if (OP(scan) == EXACT) {
        I32 l = STR_LEN(scan);
        UV uc = *((U8*)STRING(scan));
        if (UTF) {
        const U8 * const s = (U8*)STRING(scan);
        l = utf8_length((U8 *)s, (U8 *)s + l);
        uc = utf8_to_uvchr((U8 *)s, NULL);
        }
        min += l;
        if (flags & SCF_DO_SUBSTR) { /* Update longest substr. */
        /* The code below prefers earlier match for fixed
           offset, later match for variable offset.  */
        if (data->last_end == -1) { /* Update the start info. */
            data->last_start_min = data->pos_min;
             data->last_start_max = is_inf
             ? I32_MAX : data->pos_min + data->pos_delta;
        }
        sv_catpvn(data->last_found, STRING(scan), STR_LEN(scan));
        {
            SV * const sv = data->last_found;
            MAGIC * const mg = SvUTF8(sv) && SvMAGICAL(sv) ?
            mg_find(sv, PERL_MAGIC_utf8) : NULL;
            if (mg && mg->mg_len >= 0)
            mg->mg_len += utf8_length((U8*)STRING(scan),
                          (U8*)STRING(scan)+STR_LEN(scan));
        }
        if (UTF)
            SvUTF8_on(data->last_found);
        data->last_end = data->pos_min + l;
        data->pos_min += l; /* As in the first entry. */
        data->flags &= ~SF_BEFORE_EOL;
        }
        if (flags & SCF_DO_STCLASS_AND) {
        /* Check whether it is compatible with what we know already! */
        int compat = 1;

        if (uc >= 0x100 ||
            (!(data->start_class->flags & (ANYOF_CLASS | ANYOF_LOCALE))
            && !ANYOF_BITMAP_TEST(data->start_class, uc)
            && (!(data->start_class->flags & ANYOF_FOLD)
            || !ANYOF_BITMAP_TEST(data->start_class, PL_fold[uc])))
                    )
            compat = 0;
        ANYOF_CLASS_ZERO(data->start_class);
        ANYOF_BITMAP_ZERO(data->start_class);
        if (compat)
            ANYOF_BITMAP_SET(data->start_class, uc);
        data->start_class->flags &= ~ANYOF_EOS;
        if (uc < 0x100)
          data->start_class->flags &= ~ANYOF_UNICODE_ALL;
        }
        else if (flags & SCF_DO_STCLASS_OR) {
        /* false positive possible if the class is case-folded */
        if (uc < 0x100)
            ANYOF_BITMAP_SET(data->start_class, uc);
        else
            data->start_class->flags |= ANYOF_UNICODE_ALL;
        data->start_class->flags &= ~ANYOF_EOS;
        cl_and(data->start_class, &and_with);
        }
        flags &= ~SCF_DO_STCLASS;
    }
    else if (PL_regkind[(U8)OP(scan)] == EXACT) { /* But OP != EXACT! */
        I32 l = STR_LEN(scan);
        UV uc = *((U8*)STRING(scan));

        /* Search for fixed substrings supports EXACT only. */
        if (flags & SCF_DO_SUBSTR)
        scan_commit(pRExC_state, data);
        if (UTF) {
        U8 *s = (U8 *)STRING(scan);
        l = utf8_length(s, s + l);
        uc = utf8_to_uvchr(s, NULL);
        }
        min += l;
        if (data && (flags & SCF_DO_SUBSTR))
        data->pos_min += l;
        if (flags & SCF_DO_STCLASS_AND) {
        /* Check whether it is compatible with what we know already! */
        int compat = 1;

        if (uc >= 0x100 ||
            (!(data->start_class->flags & (ANYOF_CLASS | ANYOF_LOCALE))
            && !ANYOF_BITMAP_TEST(data->start_class, uc)
             && !ANYOF_BITMAP_TEST(data->start_class, PL_fold[uc])))
            compat = 0;
        ANYOF_CLASS_ZERO(data->start_class);
        ANYOF_BITMAP_ZERO(data->start_class);
        if (compat) {
            ANYOF_BITMAP_SET(data->start_class, uc);
            data->start_class->flags &= ~ANYOF_EOS;
            data->start_class->flags |= ANYOF_FOLD;
            if (OP(scan) == EXACTFL)
            data->start_class->flags |= ANYOF_LOCALE;
        }
        }
        else if (flags & SCF_DO_STCLASS_OR) {
        if (data->start_class->flags & ANYOF_FOLD) {
            /* false positive possible if the class is case-folded.
               Assume that the locale settings are the same... */
            if (uc < 0x100)
            ANYOF_BITMAP_SET(data->start_class, uc);
            data->start_class->flags &= ~ANYOF_EOS;
        }
        cl_and(data->start_class, &and_with);
        }
        flags &= ~SCF_DO_STCLASS;
    }
    else if (strchr((const char*)PL_varies,OP(scan))) {
        I32 mincount, maxcount, minnext, deltanext, fl = 0;
        I32 f = flags, pos_before = 0;
        regnode *oscan = scan;
        struct regnode_charclass_class this_class;
        struct regnode_charclass_class *oclass = NULL;
        I32 next_is_eval = 0;

        switch (PL_regkind[(U8)OP(scan)]) {
        case WHILEM:        /* End of (?:...)* . */
        scan = NEXTOPER(scan);
        goto finish;
        case PLUS:
        if (flags & (SCF_DO_SUBSTR | SCF_DO_STCLASS)) {
            next = NEXTOPER(scan);
            if (OP(next) == EXACT || (flags & SCF_DO_STCLASS)) {
            mincount = 1;
            maxcount = REG_INFTY;
            next = regnext(scan);
            scan = NEXTOPER(scan);
            goto do_curly;
            }
        }
        if (flags & SCF_DO_SUBSTR)
            data->pos_min++;
        min++;
        /* Fall through. */
        case STAR:
        if (flags & SCF_DO_STCLASS) {
            mincount = 0;
            maxcount = REG_INFTY;
            next = regnext(scan);
            scan = NEXTOPER(scan);
            goto do_curly;
        }
        is_inf = is_inf_internal = 1;
        scan = regnext(scan);
        if (flags & SCF_DO_SUBSTR) {
            scan_commit(pRExC_state, data); /* Cannot extend fixed substrings */
            data->longest = &(data->longest_float);
        }
        goto optimize_curly_tail;
        case CURLY:
        mincount = ARG1(scan);
        maxcount = ARG2(scan);
        next = regnext(scan);
        if (OP(scan) == CURLYX) {
            I32 lp = (data ? *(data->last_closep) : 0);

            scan->flags = ((lp <= U8_MAX) ? lp : U8_MAX);
        }
        scan = NEXTOPER(scan) + EXTRA_STEP_2ARGS;
        next_is_eval = (OP(scan) == EVAL);
          do_curly:
        if (flags & SCF_DO_SUBSTR) {
            if (mincount == 0) scan_commit(pRExC_state,data); /* Cannot extend fixed substrings */
            pos_before = data->pos_min;
        }
        if (data) {
            fl = data->flags;
            data->flags &= ~(SF_HAS_PAR|SF_IN_PAR|SF_HAS_EVAL);
            if (is_inf)
            data->flags |= SF_IS_INF;
        }
        if (flags & SCF_DO_STCLASS) {
            cl_init(pRExC_state, &this_class);
            oclass = data->start_class;
            data->start_class = &this_class;
            f |= SCF_DO_STCLASS_AND;
            f &= ~SCF_DO_STCLASS_OR;
        }
        /* These are the cases when once a subexpression
           fails at a particular position, it cannot succeed
           even after backtracking at the enclosing scope.
        
           XXXX what if minimal match and we are at the
                initial run of {n,m}? */
        if ((mincount != maxcount - 1) && (maxcount != REG_INFTY))
            f &= ~SCF_WHILEM_VISITED_POS;

        /* This will finish on WHILEM, setting scan, or on NULL: */
        minnext = study_chunk(pRExC_state, &scan, &deltanext, last, data,
                      mincount == 0
                    ? (f & ~SCF_DO_SUBSTR) : f);

        if (flags & SCF_DO_STCLASS)
            data->start_class = oclass;
        if (mincount == 0 || minnext == 0) {
            if (flags & SCF_DO_STCLASS_OR) {
            cl_or(pRExC_state, data->start_class, &this_class);
            }
            else if (flags & SCF_DO_STCLASS_AND) {
            /* Switch to OR mode: cache the old value of
             * data->start_class */
            StructCopy(data->start_class, &and_with,
                   struct regnode_charclass_class);
            flags &= ~SCF_DO_STCLASS_AND;
            StructCopy(&this_class, data->start_class,
                   struct regnode_charclass_class);
            flags |= SCF_DO_STCLASS_OR;
            data->start_class->flags |= ANYOF_EOS;
            }
        } else {        /* Non-zero len */
            if (flags & SCF_DO_STCLASS_OR) {
            cl_or(pRExC_state, data->start_class, &this_class);
            cl_and(data->start_class, &and_with);
            }
            else if (flags & SCF_DO_STCLASS_AND)
            cl_and(data->start_class, &this_class);
            flags &= ~SCF_DO_STCLASS;
        }
        if (!scan)         /* It was not CURLYX, but CURLY. */
            scan = next;
        if ( /* ? quantifier ok, except for (?{ ... }) */
            (next_is_eval || !(mincount == 0 && maxcount == 1))
            && (minnext == 0) && (deltanext == 0)
            && data && !(data->flags & (SF_HAS_PAR|SF_IN_PAR))
            && maxcount <= REG_INFTY/3 /* Complement check for big count */
            && ckWARN(WARN_REGEXP))
        {
            vWARN(RExC_parse,
              "Quantifier unexpected on zero-length expression");
        }

        min += minnext * mincount;
        is_inf_internal |= ((maxcount == REG_INFTY
                     && (minnext + deltanext) > 0)
                    || deltanext == I32_MAX);
        is_inf |= is_inf_internal;
        delta += (minnext + deltanext) * maxcount - minnext * mincount;

        /* Try powerful optimization CURLYX => CURLYN. */
        if (  OP(oscan) == CURLYX && data
              && data->flags & SF_IN_PAR
              && !(data->flags & SF_HAS_EVAL)
              && !deltanext && minnext == 1 ) {
            /* Try to optimize to CURLYN.  */
            regnode *nxt = NEXTOPER(oscan) + EXTRA_STEP_2ARGS;
            regnode *nxt1 = nxt;
#ifdef DEBUGGING
            regnode *nxt2;
#endif

            /* Skip open. */
            nxt = regnext(nxt);
            if (!strchr((const char*)PL_simple,OP(nxt))
            && !(PL_regkind[(U8)OP(nxt)] == EXACT
                 && STR_LEN(nxt) == 1))
            goto nogo;
#ifdef DEBUGGING
            nxt2 = nxt;
#endif
            nxt = regnext(nxt);
            if (OP(nxt) != CLOSE)
            goto nogo;
            /* Now we know that nxt2 is the only contents: */
            oscan->flags = (U8)ARG(nxt);
            OP(oscan) = CURLYN;
            OP(nxt1) = NOTHING;    /* was OPEN. */
#ifdef DEBUGGING
            OP(nxt1 + 1) = OPTIMIZED; /* was count. */
            NEXT_OFF(nxt1+ 1) = 0; /* just for consistancy. */
            NEXT_OFF(nxt2) = 0;    /* just for consistancy with CURLY. */
            OP(nxt) = OPTIMIZED;    /* was CLOSE. */
            OP(nxt + 1) = OPTIMIZED; /* was count. */
            NEXT_OFF(nxt+ 1) = 0; /* just for consistancy. */
#endif
        }
          nogo:

        /* Try optimization CURLYX => CURLYM. */
        if (  OP(oscan) == CURLYX && data
              && !(data->flags & SF_HAS_PAR)
              && !(data->flags & SF_HAS_EVAL)
              && !deltanext    /* atom is fixed width */
              && minnext != 0    /* CURLYM can't handle zero width */
        ) {
            /* XXXX How to optimize if data == 0? */
            /* Optimize to a simpler form.  */
            regnode *nxt = NEXTOPER(oscan) + EXTRA_STEP_2ARGS; /* OPEN */
            regnode *nxt2;

            OP(oscan) = CURLYM;
            while ( (nxt2 = regnext(nxt)) /* skip over embedded stuff*/
                && (OP(nxt2) != WHILEM))
            nxt = nxt2;
            OP(nxt2)  = SUCCEED; /* Whas WHILEM */
            /* Need to optimize away parenths. */
            if (data->flags & SF_IN_PAR) {
            /* Set the parenth number.  */
            regnode *nxt1 = NEXTOPER(oscan) + EXTRA_STEP_2ARGS; /* OPEN*/

            if (OP(nxt) != CLOSE)
                FAIL("Panic opt close");
            oscan->flags = (U8)ARG(nxt);
            OP(nxt1) = OPTIMIZED;    /* was OPEN. */
            OP(nxt) = OPTIMIZED;    /* was CLOSE. */
#ifdef DEBUGGING
            OP(nxt1 + 1) = OPTIMIZED; /* was count. */
            OP(nxt + 1) = OPTIMIZED; /* was count. */
            NEXT_OFF(nxt1 + 1) = 0; /* just for consistancy. */
            NEXT_OFF(nxt + 1) = 0; /* just for consistancy. */
#endif
#if 0
            while ( nxt1 && (OP(nxt1) != WHILEM)) {
                regnode *nnxt = regnext(nxt1);
            
                if (nnxt == nxt) {
                if (reg_off_by_arg[OP(nxt1)])
                    ARG_SET(nxt1, nxt2 - nxt1);
                else if (nxt2 - nxt1 < U16_MAX)
                    NEXT_OFF(nxt1) = nxt2 - nxt1;
                else
                    OP(nxt) = NOTHING;    /* Cannot beautify */
                }
                nxt1 = nnxt;
            }
#endif
            /* Optimize again: */
            study_chunk(pRExC_state, &nxt1, &deltanext, nxt,
                    NULL, 0);
            }
            else
            oscan->flags = 0;
        }
        else if ((OP(oscan) == CURLYX)
             && (flags & SCF_WHILEM_VISITED_POS)
             /* See the comment on a similar expression above.
                However, this time it not a subexpression
                we care about, but the expression itself. */
             && (maxcount == REG_INFTY)
             && data && ++data->whilem_c < 16) {
            /* This stays as CURLYX, we can put the count/of pair. */
            /* Find WHILEM (as in regexec.c) */
            regnode *nxt = oscan + NEXT_OFF(oscan);

            if (OP(PREVOPER(nxt)) == NOTHING) /* LONGJMP */
            nxt += ARG(nxt);
            PREVOPER(nxt)->flags = (U8)(data->whilem_c
            | (RExC_whilem_seen << 4)); /* On WHILEM */
        }
        if (data && fl & (SF_HAS_PAR|SF_IN_PAR))
            pars++;
        if (flags & SCF_DO_SUBSTR) {
            SV *last_str = Nullsv;
            int counted = mincount != 0;

            if (data->last_end > 0 && mincount != 0) { /* Ends with a string. */
#if defined(SPARC64_GCC_WORKAROUND)
            I32 b = 0;
            STRLEN l = 0;
            const char *s = NULL;
            I32 old = 0;

            if (pos_before >= data->last_start_min)
                b = pos_before;
            else
                b = data->last_start_min;

            l = 0;
            s = SvPV_const(data->last_found, l);
            old = b - data->last_start_min;

#else
            I32 b = pos_before >= data->last_start_min
                ? pos_before : data->last_start_min;
            STRLEN l;
            const char *s = SvPV_const(data->last_found, l);
            I32 old = b - data->last_start_min;
#endif

            if (UTF)
                old = utf8_hop((U8*)s, old) - (U8*)s;
            
            l -= old;
            /* Get the added string: */
            last_str = newSVpvn(s  + old, l);
            if (UTF)
                SvUTF8_on(last_str);
            if (deltanext == 0 && pos_before == b) {
                /* What was added is a constant string */
                if (mincount > 1) {
                SvGROW(last_str, (mincount * l) + 1);
                repeatcpy(SvPVX(last_str) + l,
                      SvPVX_const(last_str), l, mincount - 1);
                SvCUR_set(last_str, SvCUR(last_str) * mincount);
                /* Add additional parts. */
                SvCUR_set(data->last_found,
                      SvCUR(data->last_found) - l);
                sv_catsv(data->last_found, last_str);
                {
                    SV * sv = data->last_found;
                    MAGIC *mg =
                    SvUTF8(sv) && SvMAGICAL(sv) ?
                    mg_find(sv, PERL_MAGIC_utf8) : NULL;
                    if (mg && mg->mg_len >= 0)
                    mg->mg_len += CHR_SVLEN(last_str);
                }
                data->last_end += l * (mincount - 1);
                }
            } else {
                /* start offset must point into the last copy */
                data->last_start_min += minnext * (mincount - 1);
                data->last_start_max += is_inf ? I32_MAX
                : (maxcount - 1) * (minnext + data->pos_delta);
            }
            }
            /* It is counted once already... */
            data->pos_min += minnext * (mincount - counted);
            data->pos_delta += - counted * deltanext +
            (minnext + deltanext) * maxcount - minnext * mincount;
            if (mincount != maxcount) {
             /* Cannot extend fixed substrings found inside
                the group.  */
            scan_commit(pRExC_state,data);
            if (mincount && last_str) {
                sv_setsv(data->last_found, last_str);
                data->last_end = data->pos_min;
                data->last_start_min =
                data->pos_min - CHR_SVLEN(last_str);
                data->last_start_max = is_inf
                ? I32_MAX
                : data->pos_min + data->pos_delta
                - CHR_SVLEN(last_str);
            }
            data->longest = &(data->longest_float);
            }
            SvREFCNT_dec(last_str);
        }
        if (data && (fl & SF_HAS_EVAL))
            data->flags |= SF_HAS_EVAL;
          optimize_curly_tail:
        if (OP(oscan) != CURLYX) {
            while (PL_regkind[(U8)OP(next = regnext(oscan))] == NOTHING
               && NEXT_OFF(next))
            NEXT_OFF(oscan) += NEXT_OFF(next);
        }
        continue;
        default:            /* REF and CLUMP only? */
        if (flags & SCF_DO_SUBSTR) {
            scan_commit(pRExC_state,data);    /* Cannot expect anything... */
            data->longest = &(data->longest_float);
        }
        is_inf = is_inf_internal = 1;
        if (flags & SCF_DO_STCLASS_OR)
            cl_anything(pRExC_state, data->start_class);
        flags &= ~SCF_DO_STCLASS;
        break;
        }
    }
    else if (strchr((const char*)PL_simple,OP(scan))) {
        int value = 0;

        if (flags & SCF_DO_SUBSTR) {
        scan_commit(pRExC_state,data);
        data->pos_min++;
        }
        min++;
        if (flags & SCF_DO_STCLASS) {
        data->start_class->flags &= ~ANYOF_EOS;    /* No match on empty */

        /* Some of the logic below assumes that switching
           locale on will only add false positives. */
        switch (PL_regkind[(U8)OP(scan)]) {
        case SANY:
        default:
          do_default:
            /* Perl_croak(aTHX_ "panic: unexpected simple REx opcode %d", OP(scan)); */
            if (flags & SCF_DO_STCLASS_OR) /* Allow everything */
            cl_anything(pRExC_state, data->start_class);
            break;
        case REG_ANY:
            if (OP(scan) == SANY)
            goto do_default;
            if (flags & SCF_DO_STCLASS_OR) { /* Everything but \n */
            value = (ANYOF_BITMAP_TEST(data->start_class,'\n')
                 || (data->start_class->flags & ANYOF_CLASS));
            cl_anything(pRExC_state, data->start_class);
            }
            if (flags & SCF_DO_STCLASS_AND || !value)
            ANYOF_BITMAP_CLEAR(data->start_class,'\n');
            break;
        case ANYOF:
            if (flags & SCF_DO_STCLASS_AND)
            cl_and(data->start_class,
                   (struct regnode_charclass_class*)scan);
            else
            cl_or(pRExC_state, data->start_class,
                  (struct regnode_charclass_class*)scan);
            break;
        case ALNUM:
            if (flags & SCF_DO_STCLASS_AND) {
            if (!(data->start_class->flags & ANYOF_LOCALE)) {
                ANYOF_CLASS_CLEAR(data->start_class,ANYOF_NALNUM);
                for (value = 0; value < 256; value++)
                if (!isALNUM(value))
                    ANYOF_BITMAP_CLEAR(data->start_class, value);
            }
            }
            else {
            if (data->start_class->flags & ANYOF_LOCALE)
                ANYOF_CLASS_SET(data->start_class,ANYOF_ALNUM);
            else {
                for (value = 0; value < 256; value++)
                if (isALNUM(value))
                    ANYOF_BITMAP_SET(data->start_class, value);            
            }
            }
            break;
        case ALNUML:
            if (flags & SCF_DO_STCLASS_AND) {
            if (data->start_class->flags & ANYOF_LOCALE)
                ANYOF_CLASS_CLEAR(data->start_class,ANYOF_NALNUM);
            }
            else {
            ANYOF_CLASS_SET(data->start_class,ANYOF_ALNUM);
            data->start_class->flags |= ANYOF_LOCALE;
            }
            break;
        case NALNUM:
            if (flags & SCF_DO_STCLASS_AND) {
            if (!(data->start_class->flags & ANYOF_LOCALE)) {
                ANYOF_CLASS_CLEAR(data->start_class,ANYOF_ALNUM);
                for (value = 0; value < 256; value++)
                if (isALNUM(value))
                    ANYOF_BITMAP_CLEAR(data->start_class, value);
            }
            }
            else {
            if (data->start_class->flags & ANYOF_LOCALE)
                ANYOF_CLASS_SET(data->start_class,ANYOF_NALNUM);
            else {
                for (value = 0; value < 256; value++)
                if (!isALNUM(value))
                    ANYOF_BITMAP_SET(data->start_class, value);            
            }
            }
            break;
        case NALNUML:
            if (flags & SCF_DO_STCLASS_AND) {
            if (data->start_class->flags & ANYOF_LOCALE)
                ANYOF_CLASS_CLEAR(data->start_class,ANYOF_ALNUM);
            }
            else {
            data->start_class->flags |= ANYOF_LOCALE;
            ANYOF_CLASS_SET(data->start_class,ANYOF_NALNUM);
            }
            break;
        case SPACE:
            if (flags & SCF_DO_STCLASS_AND) {
            if (!(data->start_class->flags & ANYOF_LOCALE)) {
                ANYOF_CLASS_CLEAR(data->start_class,ANYOF_NSPACE);
                for (value = 0; value < 256; value++)
                if (!isSPACE(value))
                    ANYOF_BITMAP_CLEAR(data->start_class, value);
            }
            }
            else {
            if (data->start_class->flags & ANYOF_LOCALE)
                ANYOF_CLASS_SET(data->start_class,ANYOF_SPACE);
            else {
                for (value = 0; value < 256; value++)
                if (isSPACE(value))
                    ANYOF_BITMAP_SET(data->start_class, value);            
            }
            }
            break;
        case SPACEL:
            if (flags & SCF_DO_STCLASS_AND) {
            if (data->start_class->flags & ANYOF_LOCALE)
                ANYOF_CLASS_CLEAR(data->start_class,ANYOF_NSPACE);
            }
            else {
            data->start_class->flags |= ANYOF_LOCALE;
            ANYOF_CLASS_SET(data->start_class,ANYOF_SPACE);
            }
            break;
        case NSPACE:
            if (flags & SCF_DO_STCLASS_AND) {
            if (!(data->start_class->flags & ANYOF_LOCALE)) {
                ANYOF_CLASS_CLEAR(data->start_class,ANYOF_SPACE);
                for (value = 0; value < 256; value++)
                if (isSPACE(value))
                    ANYOF_BITMAP_CLEAR(data->start_class, value);
            }
            }
            else {
            if (data->start_class->flags & ANYOF_LOCALE)
                ANYOF_CLASS_SET(data->start_class,ANYOF_NSPACE);
            else {
                for (value = 0; value < 256; value++)
                if (!isSPACE(value))
                    ANYOF_BITMAP_SET(data->start_class, value);            
            }
            }
            break;
        case NSPACEL:
            if (flags & SCF_DO_STCLASS_AND) {
            if (data->start_class->flags & ANYOF_LOCALE) {
                ANYOF_CLASS_CLEAR(data->start_class,ANYOF_SPACE);
                for (value = 0; value < 256; value++)
                if (!isSPACE(value))
                    ANYOF_BITMAP_CLEAR(data->start_class, value);
            }
            }
            else {
            data->start_class->flags |= ANYOF_LOCALE;
            ANYOF_CLASS_SET(data->start_class,ANYOF_NSPACE);
            }
            break;
        case DIGIT:
            if (flags & SCF_DO_STCLASS_AND) {
            ANYOF_CLASS_CLEAR(data->start_class,ANYOF_NDIGIT);
            for (value = 0; value < 256; value++)
                if (!isDIGIT(value))
                ANYOF_BITMAP_CLEAR(data->start_class, value);
            }
            else {
            if (data->start_class->flags & ANYOF_LOCALE)
                ANYOF_CLASS_SET(data->start_class,ANYOF_DIGIT);
            else {
                for (value = 0; value < 256; value++)
                if (isDIGIT(value))
                    ANYOF_BITMAP_SET(data->start_class, value);            
            }
            }
            break;
        case NDIGIT:
            if (flags & SCF_DO_STCLASS_AND) {
            ANYOF_CLASS_CLEAR(data->start_class,ANYOF_DIGIT);
            for (value = 0; value < 256; value++)
                if (isDIGIT(value))
                ANYOF_BITMAP_CLEAR(data->start_class, value);
            }
            else {
            if (data->start_class->flags & ANYOF_LOCALE)
                ANYOF_CLASS_SET(data->start_class,ANYOF_NDIGIT);
            else {
                for (value = 0; value < 256; value++)
                if (!isDIGIT(value))
                    ANYOF_BITMAP_SET(data->start_class, value);            
            }
            }
            break;
        }
        if (flags & SCF_DO_STCLASS_OR)
            cl_and(data->start_class, &and_with);
        flags &= ~SCF_DO_STCLASS;
        }
    }
    else if (PL_regkind[(U8)OP(scan)] == EOL && flags & SCF_DO_SUBSTR) {
        data->flags |= (OP(scan) == MEOL
                ? SF_BEFORE_MEOL
                : SF_BEFORE_SEOL);
    }
    else if (  PL_regkind[(U8)OP(scan)] == BRANCHJ
         /* Lookbehind, or need to calculate parens/evals/stclass: */
           && (scan->flags || data || (flags & SCF_DO_STCLASS))
           && (OP(scan) == IFMATCH || OP(scan) == UNLESSM)) {
        /* Lookahead/lookbehind */
        I32 deltanext, minnext, fake = 0;
        regnode *nscan;
        struct regnode_charclass_class intrnl;
        int f = 0;

        data_fake.flags = 0;
        if (data) {        
        data_fake.whilem_c = data->whilem_c;
        data_fake.last_closep = data->last_closep;
        }
        else
        data_fake.last_closep = &fake;
        if ( flags & SCF_DO_STCLASS && !scan->flags
         && OP(scan) == IFMATCH ) { /* Lookahead */
        cl_init(pRExC_state, &intrnl);
        data_fake.start_class = &intrnl;
        f |= SCF_DO_STCLASS_AND;
        }
        if (flags & SCF_WHILEM_VISITED_POS)
        f |= SCF_WHILEM_VISITED_POS;
        next = regnext(scan);
        nscan = NEXTOPER(NEXTOPER(scan));
        minnext = study_chunk(pRExC_state, &nscan, &deltanext, last, &data_fake, f);
        if (scan->flags) {
        if (deltanext) {
            vFAIL("Variable length lookbehind not implemented");
        }
        else if (minnext > U8_MAX) {
            vFAIL2("Lookbehind longer than %"UVuf" not implemented", (UV)U8_MAX);
        }
        scan->flags = (U8)minnext;
        }
        if (data && data_fake.flags & (SF_HAS_PAR|SF_IN_PAR))
        pars++;
        if (data && (data_fake.flags & SF_HAS_EVAL))
        data->flags |= SF_HAS_EVAL;
        if (data)
        data->whilem_c = data_fake.whilem_c;
        if (f & SCF_DO_STCLASS_AND) {
        const int was = (data->start_class->flags & ANYOF_EOS);

        cl_and(data->start_class, &intrnl);
        if (was)
            data->start_class->flags |= ANYOF_EOS;
        }
    }
    else if (OP(scan) == OPEN) {
        pars++;
    }
    else if (OP(scan) == CLOSE) {
        if ((I32)ARG(scan) == is_par) {
        next = regnext(scan);

        if ( next && (OP(next) != WHILEM) && next < last)
            is_par = 0;        /* Disable optimization */
        }
        if (data)
        *(data->last_closep) = ARG(scan);
    }
    else if (OP(scan) == EVAL) {
        if (data)
            data->flags |= SF_HAS_EVAL;
    }
    else if (OP(scan) == LOGICAL && scan->flags == 2) { /* Embedded follows */
        if (flags & SCF_DO_SUBSTR) {
            scan_commit(pRExC_state,data);
            data->longest = &(data->longest_float);
        }
        is_inf = is_inf_internal = 1;
        if (flags & SCF_DO_STCLASS_OR) /* Allow everything */
            cl_anything(pRExC_state, data->start_class);
        flags &= ~SCF_DO_STCLASS;
    }
    /* Else: zero-length, ignore. */
    scan = regnext(scan);
    }

  finish:
    *scanp = scan;
    *deltap = is_inf_internal ? I32_MAX : delta;
    if (flags & SCF_DO_SUBSTR && is_inf)
    data->pos_delta = I32_MAX - data->pos_min;
    if (is_par > U8_MAX)
    is_par = 0;
    if (is_par && pars==1 && data) {
    data->flags |= SF_IN_PAR;
    data->flags &= ~SF_HAS_PAR;
    }
    else if (pars && data) {
    data->flags |= SF_HAS_PAR;
    data->flags &= ~SF_IN_PAR;
    }
    if (flags & SCF_DO_STCLASS_OR)
    cl_and(data->start_class, &and_with);
    return min;
}

А метка в конце — finish
http://zoozahita.ruБездомные животные Екатеринбурга ищут хозяев
Re[5]: Исходники Perl...
От: . Великобритания  
Дата: 08.02.07 10:50
Оценка:
SergeCpp wrote:

> Полюбуйтесь на файл regcomp.c <http://rsdn.ru/File/44396/regcomp.c&gt;

Подумаешь... Всего 150к. Вот посолиднее будет http://svn.gnome.org/svn/libxml2/trunk/xmlschemas.c
Posted via RSDN NNTP Server 2.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[7]: объект-механизм
От: SergeCpp Россия http://zoozahita.ru
Дата: 08.02.07 11:01
Оценка: 12 (1) :)
Здравствуйте, Константин Л., Вы писали:

КЛ>Здравствуйте, Erop, Вы писали:


КЛ>[]


E>>Я, в таких случаях, обычно пишу объект-механизм
Автор: Erop
Дата: 12.01.07


КЛ>угу, я тоже бывает

КЛ>

У Страуструпа, вроде бы нечто подобное в D&E было.
Книги под рукой нет, поэтому не уверен, но то что видел где-то, это точно

Пива не пью, поэтому просто — виват!
http://zoozahita.ruБездомные животные Екатеринбурга ищут хозяев
Re[9]: Для Андрея Хропова, спецально
От: Erop Россия  
Дата: 08.02.07 11:34
Оценка:
Здравствуйте, Erop, Вы писали:

E>ИМХО, в области вычматов FORTRAN по переносимости далеко впереди планеты всей. Давно и надолго


Месье знает пример каких-то серъёзных проблем с переносом вычматематической задачи, реализованой на FORTRAN?..
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: [папа STL] Alexander Stepanov "Notes on Programming"
От: trophim Россия  
Дата: 10.02.07 22:55
Оценка:
Здравствуйте, Шахтер, Вы писали:

Ш>Здравствуйте, Lorenzo_LAMAS, Вы писали:


L_L>>Здравствуйте, Шахтер, Вы писали:


Ш>>>В каждой програмистской конторе написать большими буквами и прибить к стене.


L_L>>Это в башку надо вбивать, а не на стены


Ш>Знаешь как в Самсунге учат английскому?

Ш>В туалете выше писуаров на уровне глаз вешают листочки с английскими словами. Листочки регулярно меняют.
Ш>Видимо, помогает.

А словари в кабинки не вешают? Зашел, извините, по большому — оторвал листик, прочел, использовал. Словари регулярно менять.
[EOF]
Let it be! — Давайте есть пчелу!
Re[5]: [папа STL] Alexander Stepanov "Notes on Programming"
От: trophim Россия  
Дата: 10.02.07 22:55
Оценка:
Здравствуйте, MasterZiv, Вы писали:

MZ>Только у нас код хуже ...


Народ, эт самое, я вот не понял — я должен ощущать себя счастливым? У нас всего лишь функции на 2 — 5 экранов лепят и переменные обзывают s, sss, tmp etc. Я так погляжу, что вы ваще в попе.
[EOF]
Let it be! — Давайте есть пчелу!
Re: [папа STL] Alexander Stepanov "Notes on Programming"
От: Ka3a4oK  
Дата: 26.02.07 21:49
Оценка:
Я, конечно, рискую быть битым (каламбурчик ) камнями, но все-таки скажу. Я стараюсь в функцию заключать осмысленную, законченную логику. Т.е. чтобы существовала вероятность её (функции) повторного использования. Двадцать строк очень часто не получается, особенно, если обильно использовать ASSERT. Не нужны функции step1, step2 и т.п. Посмотрите исходники стандартной библиотеки C и STL. В STL особое внимание советую обратить на файлы, стыдливо спрятанные префиксом x. Плохой или хороший это код, вопрос другой.
... << RSDN@Home 1.1.4 stable rev. 510>>
Re[2]: [папа STL] Alexander Stepanov "Notes on Programming"
От: trophim Россия  
Дата: 02.03.07 22:41
Оценка: 1 (1) +3
Здравствуйте, Ka3a4oK, Вы писали:

KK>Я, конечно, рискую быть битым (каламбурчик ) камнями, но все-таки скажу. Я стараюсь в функцию заключать осмысленную, законченную логику. Т.е. чтобы существовала вероятность её (функции) повторного использования. Двадцать строк очень часто не получается, особенно, если обильно использовать ASSERT. Не нужны функции step1, step2 и т.п. Посмотрите исходники стандартной библиотеки C и STL. В STL особое внимание советую обратить на файлы, стыдливо спрятанные префиксом x. Плохой или хороший это код, вопрос другой.


Ой, а разве в коде STL можно без бутылки (чтоб сознание расширить) что-то понять (как и в некоторых библиотеках из буста)?
Имена страшные, кучи подчеркиваний, мешанина регистра букв, выравнивание какое-то иезуитское, кучи дефайнов... Вешалка в общем.
[EOF]
Let it be! — Давайте есть пчелу!
Re[5]: [папа STL] Alexander Stepanov "Notes on Programming"
От: dkotov  
Дата: 14.03.07 15:17
Оценка:
Здравствуйте, Константин Л., Вы писали:

Ничего Вы не понимаете, руки прочь от пиз...ой функции.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.