1. C++ / Говнокод #17152

    +57

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    30. 30
    31. 31
    32. 32
    33. 33
    34. 34
    35. 35
    36. 36
    37. 37
    38. 38
    39. 39
    40. 40
    41. 41
    42. 42
    43. 43
    44. 44
    45. 45
    typedef deque<uint8_t> bn;
    #define cat2(b,e) b##e
    #define cat(b,e) cat2(b,e)
    #define fsi(i,s,e) for(size_t i(s), cat(i,cat(_fsi_end_,__LINE__))(e); i<cat(i,cat(_fsi_end_,__LINE__)); ++(i))
    void ml10(bn& n){
      n.push_front(0);
    }
    uint8_t ni(const bn& n, size_t i){
      if(n.size()<=i)
        return 0;
      else
        return n[i];
    }
    size_t ms(const bn& n1, const bn& n2){
      return (max) (n1.size(), n2.size());
    }
    void pb(uint8_t b1, uint8_t b2, uint8_t lc, uint8_t& r, uint8_t& c){
      uint8_t tr = (b1+b2+lc);
      r = tr & 1;
      c = !!(tr & 2);
    }
    bn bi(bn n){
      reverse(n.begin(), n.end());
      return n;
    }
    bn pl(const bn& n1, const bn& n2){
      bn r;
      uint8_t c=0,br=0;
      fsi(i,0,ms(n1, n2)){
        pb(ni(n1,i),ni(n2,i),c,br,c);
        r.push_back(br);
      }
      if (c)
        r.push_back(c);
      return r;
    }
    bn ml(bn n1, const bn& n2){
      bn r;
      fsi(i,0,n2.size()){
        if(n2[i])
          r=pl(r,n1);
        ml10(n1);
      }
      return r;
    }

    У меня к вам вопрос парни.
    В нашем отделе взяли олимпиадника. За ним не следили. Он написал много кода и ушел в гугл.
    Как бы за ним теперь код поправить? Хотябы конструкции языка типа for вернуть вместо например fsi?
    Код не из проекта. но его. В проекте похожий и даже хуже.
    Нужно типа утилиты препроцессор крестов для части макросов (все разворачивать макросы или инклудить хедеры очевидно нельзя).

    Запостил: laMer007, 23 Ноября 2014

    Комментарии (68) RSS

    • Я думаю все догадались что это.
      Сложение и умножение двочиных чисел.
      http://ideone.com/6ZeIkX

      Пост для привлечения внимания
      Ответить
      • Знаете где он живет? За ТАКОЕ расстреливать через повешение на электрическом стуле.
        Ответить
    • > и ушел в гугл
      Вот это настораживает и в то же время многое объясняет.
      Ответить
    • Я не помню точно как, но уверен в том, что можно получить АСТ из компилятора. Дальше можно из него макросами, на Лиспе, запилить транслятор этого дерева в более вменяемый С++.

      О, кстати, это ж корпорация зла как раз такой инструмент и разрабатывает!
      http://www.phoronix.com/scan.php?page=news_item&px=MTEyMTE
      Может быть поэтому?
      Ответить
      • Не, ну все верно. Правильную идентацию или стиль мне тоже не нравится соблюдать. Я конечно это делаю, но если бы был такой рефактор у нас в отделе, то я бы с радостью им пользовался.
        Ответить
        • Вот, ради примера:

          (defun expand-fsi ()
            "Translates fsi(i, s, e) into
              for(size_t i(s), 
                  cat(i, cat(_fsi_end_, __LINE__))(e);
                  i < cat(i, cat(_fsi_end_, __LINE__));
                  ++(i))"
            (interactive)
            (cl-labels
                ((skip-exp
                  (to)
                  (buffer-substring-no-properties 
                   (point)
                   (progn
                     (while (not (looking-at to))
                       (forward-sexp))
                     (forward-char)
                     (1- (point))))))
              (when (looking-at "\\<fsi(")
                (save-excursion
                  (let ((begin (point)))
                    (forward-sexp)                      ; skip to the paren
                    (forward-char)                      ; skip the paren
                    (let ((i (skip-exp ","))
                          (s (skip-exp ","))
                          (e (skip-exp ")")))
                      (delete-region begin (point))
                      (insert (concat "for(size_t " i "(" s "), "
                                   "cat(" i ", cat(_fsi_end_, __LINE__))(" e ");\n"
                                   i " < cat(" i ", cat(_fsi_end_, __LINE__));
                                   ++(" i "))"))
                      (indent-region begin (point))))))))


          Заменяет:
          bn pl(const bn& n1, const bn& n2){
            bn r;
            uint8_t c=0,br=0;
            fsi(i,0,ms(n1, n2)){
              pb(ni(n1,i),ni(n2,i),c,br,c);
              r.push_back(br);
            }
            if (c)
              r.push_back(c);
            return r;
          }

          на
          bn pl(const bn& n1, const bn& n2){
            bn r;
            uint8_t c=0,br=0;
            for(size_t i(0), cat(i, cat(_fsi_end_, __LINE__))(ms(n1, n2));
                i < cat(i, cat(_fsi_end_, __LINE__));
                ++(i)){
              pb(ni(n1,i),ni(n2,i),c,br,c);
              r.push_back(br);
            }
            if (c)
              r.push_back(c);
            return r;
          }

          Можно и остальные макросы так же запилить, но мне влом :)
          Ответить
      • Смысл в том что товарищ хочет раскрыть только часто макросов, и как тут ему АСТ поможет?
        Ответить
        • Там как раз по ссылке пример, где АСТ используется для рефакторинга. Я просто не специалист в С++, но я так подумал, что оно и макросы может пораскрывать. Скажем так, на коленке я бы мог для этого написать макро для Эмакса, и потом вручную нужные места пораскрывать, но я хз сколько это займет по времени, тут надо более четко задачу сформулировать: сколько макросов, сколько файлов и т.д.
          Ответить
          • Ну настоящее AST для раскрытия сишных макросов не нужно. Препроцессор, емнип, на уровне токенов работает. Ну и немного понимает круглые скобки. И всё вроде бы.

            Т.е. достаточно искать "fsi(", соответствующую ")" и заменять их.
            Ответить
            • + 1 к тому, что препроцессору должно хватать лексера.

              Мне почему-то кажется что парсер бы споткнулся и умер о такое (а препроцессор работает)
              #define FOO _HUI((((,PIZA';;*()-()*;;;;DHIGURDA
              
              void main() {
              FOO
              }

              "gcc -E" прекрасно отрабатывает же.
              [/code]
              Ответить
            • Ну вот выше вариант есть. Я просто не в курсе как СРР работает.
              Ответить
    • > #define fsi(i,s,e) for(size_t i(s), cat(i,cat(_fsi_end_,__LINE__))(e); i<cat(i,cat(_fsi_end_,__LINE__)); ++(i))
      ОМГ, что это?!
      Ответить
    • Человек-обфускатор... Тут раскрытием макросов не отделаешься...
      Ответить
      • А по-моему, плохой обфускатор. Всё у человека продумано, кроме pb, из-за которого, кажется, пришлось pl, ml и ml10 так назвать.
        bn - binary number
        fsi - for(size_t i
        ni - number[i]
        ms - max size
        pb - plus bit
        bi - binary invert
        pl - plus long
        ml - mul long binary
        ml10 - mul(long binary, 0b10)
        Ответить
        • laMer007, быстро хватайте этого парня к себе в отдел, думаю он бы вам разобрал код и без всяких тулзов.
          Ответить
        • > Всё у человека продумано
          Ну а нам то что теперь делать с результатами его гениальности?
          Ладно функции мы конечно переименуем заменой.
          А вот с этим как?
          fsi(i,0,n2.size())

          Может регексами как-то в
          for(size_t i = 0; i<n2.size();++i)
          преобразовать? Или лучше даже в
          for(size_t i = 0, i_end=n2.size(); i<i_end;++i)
          ?
          Ответить
          • - комментим в файле все строки, начинающиеся с #;
            - запускаем gcc с опциями -E и -include (с файлом, в котором описаны только упрощенные версии fsi и прочей херни);
            - выносим нахер все строки, начинающиеся с #
            - раскомменчиваем закоммеченное на первом шаге;
            ???
            - профит!
            Ответить
            • P.S. -E комменты срезает, не вариант ;(
              Ответить
              • вижуальный препроцессор не выносит директивы, если их попортить перед этим, например, поставив перед решеткой минус
                комментарии можно, наверное, обезопасить, заменив регулярочкой на что-то вроде /-+/ и /-+* *-+/, чтобы потом легко было вернуть их обратно
                осталось только необходимые для разворачивания макросы вернуть к первоначальному валидному варианту и уже прогонять через препроцессор
                но ИМХО всё равно не вариант, т.к. потом слишком много ручной работы по возвращению исходников к, кхм... исходному состоянию

                UPD: ОК, это всё питушня
                всё тлен
                Ответить
                • Ниже я написал скрипт, который всё это делает на автомате. Директивы и комменты выжили.

                  Из недостатков - если в коде встречается //# - он его раскомментит. Можно вылечить более сложной защитой директив, к примеру //----#
                  Ответить
            • Вот так работает:
              cpp -E -C -P -nostdinc -include fsi.h some.cpp
              Ответить
            • -include
              Что это? Подключить хедер из командной строки?

              О вы выше ответили.

              Ну и если честно так не хотелось бы, тк в коде есть и вполне вменяемые макросы (насколько такое возможно), которым лучше ими и остаться. Например кодогенерация с BOOST_PP_REPEAT или паттерн матчинг аля:
              char c=s[i], c2=s[j];
              switch(PAIR(c,c2)){
              case PAIR('!','='):...
              case PAIR('=','='):...
              }
              Ответить
              • Именно так. Но на предыдущем шаге мы же закомментили все директивы препроцессора. И если их раскомментить после обработки приведенной выше командой - они выживут.
                Ответить
                • То есть вы предлагает закоментить все полезные макроподстановки, например PAIR и все директивы из буста? Ну бустовское коментится в данном случае за счет коментирования инклуда. Идея конечно. Это не сработает со всеми адскими макросами гения, что юзают буст к сожалению. Я надеюсь, что таких нет, но они могут быть.
                  Ну и адский результат cat(i,cat(_fsi_end_,__LINE__)) останется. Впрочем просто fsi поправлю заменив там это на кот(i##_end)
                  Ответить
                  • > Впрочем просто fsi поправлю заменив там это на кот(i##_end)
                    Ага.

                    > Это не сработает со всеми адскими макросами гения, что юзают буст к сожалению.
                    Ну тут х.з. Разве что руками замакросить их на что-то более простое и понятное...
                    Ответить
                    • > Ну тут х.з.
                      Вот если бы тут замену fsi делать регекспами на то, чем я хочу заменить или ещё чем-то кроме регекспов, то этой бы проблемы конечно не было бы, тк мог бы избирательно раскрывать макросы не раскрывая, а заменяя. Может boost::wave что-то такое может? Ну или хотябы избирательно может раскрывать?
                      Ответить
              • Вот такой алгоритм (потестил, вроде работает, другие макросы выжили, и даже комменты остались):
                # блокируем все директивы препроцессора
                sed 's/#/\/\/#/' <some.cpp >some.1.cpp
                # раскрываем говно
                cpp -E -C -P -nostdinc -include fsi.h some.1.cpp >some.2.cpp
                # снимаем блокировку с директив
                sed 's/\/\/#/#/' <some.2.cpp >some.cpp
                Ответить
                • О, тут алгоритмы пошли... А я утром написал свою блокирующую питушню, но постеснялся выложить, т.к. толку от неё было мало.
                  Но может, флаги Борманда для компилятора помогут вместе с -E получить на выходе меньше питушни.

                  http://pastebin.com/5vBwLXph
                  0. Сохраняем код в preproc.js, бэкапим файлы олимпиадника
                  1. Берём файл file.cc с кодом олимпиадника
                  2. node preproc info file.cc options.txt
                  3. удаляем из вновь созданного options.txt всё то, что следует заинклюдить/раскрыть. Т.е. оставляем в options.txt все макросы/файлы, которые написал не Царь он.
                  4. node preproc comment file.cc file1.cc options.txt
                  5. gcc -E <ещё какие флаги> file1.cc > file2.cc
                  6. node preproc uncomment file2.cc file3.cc
                  7. удаляем из file3.cc лишнюю питушню. file3.cc - новый файл с раскрытыми макросами.
                  Ответить
                  • Лал. Я конечно не пробовал, но вы какую-то хрень несете. Все эти раскрытия макросов удалят из кода всю индентацию и переносы строк в многострочных макросах. Во потом заказчик код будет читать.

                    О кстати. Я придумал. Пойду в фрланс. Буду фигачить там код этими макросами. Затем методом бормонда если заказчику не понравится - рамкрывать макросы. А если понравиться, то и черт с ним. Главное быстро.
                    Ответить
                    • Х.з., я тестил свой способ - ничего лишнего не удалилось. Комменты на месте, отступы на месте, макросы на месте.
                      Ответить
                      • >> в многострочных макросах
                        И правда, мой код вызовет сущий ад на ровном месте, если автор написал
                        #define pit \
                          uh = 4;

                        Первая строка закомментируется, вторая останется.
                        Ответить
                        • А вторая строка не мешает. У нее же нету #, и препроцессор ее не заметит и оставит как есть.
                          Ответить
                      • Ну а прикинь если надо раскрыть макроподстановку с
                        do{
                        statment;
                        }while(false)

                        Прикинь в код после раскрытия эта байда с do while говном встанет? Это явно заказчик одобрит, что по всему коду разбросан такой ад
                        Ответить
                        • Дык нам не надо подставлять ее дословно. Более того, нам надо раскрыть ее не в то, что хотел изначальный автор, а в нечто красивое и читабельное. Поэтому этой проблемы не будет.

                          P.S. Хотя... тогда придется ревьювить все точки, в которых раскрыт макрос :( Этот do while все-таки не от хорошей жизни втыкали.

                          Так что с такими макросами считерить не выйдет ;(
                          Ответить
          • Хм. Регекспы не смогут обработать какой-то такой случай:
            fsi(i,0,f(x,y))

            Тк теперь в макросне 3 запятых вместо двух. То есть таким макросом возможно будет поправить только простые случаи. Хотя конечно их большинство должно быть, так что уже хотябы часть проблем решим и не придется делать это вручную.
            Ответить
          • > Может регексами как-то в преобразовать?
            Вполне можно? если там чего хтирого не понапихано, с запятыми в вызовах fsi :)
            Ответить
        • > bi - binary invert
          Должно быть тогда ib. У него везде глагол вначале идет по вашей задумке. Единственное что радует это наличие коротких функций, по телу которых хотябы понятно что они делают.
          Ответить
          • Мастер ещё не достиг совершенства. Следите за обновлениями!
            * или я грешный посмел толковать волю Высшего Разума и сделал это неправильно
            Ответить
    • А вот меня этот код прикалывает. Я напишу оптимальнее. Ваш гений - лох. Умножать числа в двоичном виде очень медленно и потребляет много памяти. Я буду в 16тиричном. Челендж ацептед.
      Ответить
      • > Я буду в 16тиричном
        А смысл? Мути уж тогда через какие-нибудь uint8_t или даже uint32_t...
        Ответить
        • ну так и задумано. Просто запишу типа 0xFFFFFFFF чтобы в крестах красиво смотрелось, а по сути будет uint32_t
          Ответить
          • Вы недумайте что я слился. Мне просто лень. Я аниме смотрю
            Ответить
            • > Я аниме смотрю
              Фу-фу-фу
              Ответить
              • Ну лень мне было писать. Неужто и отдохнуть в выходные нельзя?
                http://govnokod.ru/17155

                >Фу-фу-фу
                А судьи кто?
                Ответить
    • Вот поэтому олимпиадников нельзя подпускать к продакшену. На олимпиадах условие - в очень сжатые сроки наклепать код "на раз" неважно какой степени жуткости, главное - чтоб работало. А потом они отвыкают писать сопровождаемый код.
      Ответить
      • А нах тогда этот парень гуглу? Так что видать можно при каких-то условиях. Ты просто завидуешь олимпиадникам. Небось олимпиадник жену увёл.
        Ответить
    • А че, кодревью, кодинг стандарт, всякие линты и анализаторы, регулярно запускаемые на билдсервере, уже не в моде в серьезных конторах?
      Любой из этих пунктов решил бы проблему в зародыше.
      Ответить
      • Они ни разу в код не заглянули, а ты - линты, ревью, стандарты...
        Ответить
      • Какие стандарты, какие анализаторы?!
        Главное - взять в команду побольше олимпиадников, и успех обеспечен! У Дурова же "получилось"!
        Ответить
        • и где теперь Дуров? А казалось причем тут Олимпиадники.
          Ответить
          • Дуров заработал много денег и теперь пилит телеграмм) Олимпиадники тут ни при чем: Дуров очень правильно построил маркетинг, грамотно провёл пиар, качество программистов тут не важно, имхо)
            Ответить
            • >Дуров очень правильно построил маркетинг, грамотно провёл пиар, качество программистов тут не важно
              Стопудов. Как и выбранные языки разработки. Вот все говнят рнр и js, но вк они приносят деньги.
              Но всё же я что-то сомневаюсь что Дуров лично рулил именно это самой важной бизнес-составляющей.
              Там же сначала совершенно не было никакой монетизации, даже реклама отсутствовала, а мощности и траффик требовались громаднейшие. И что он годами, себе в убыток финансировал проект на этапе начальной раскрутки.
              Ответить
              • ЕМНИП в Дурова инвестировали. Один из его однокашников (чуть ли не с родителями своими на пару) вложил в его проект кучу денег, так что деньги у него изначально были.
                Ответить
                • >Один из его однокашников (чуть ли не с родителями своими на пару)
                  Это какая-то кулстори для прессы. Про историю успеха простого русского пацана, который упорным трудом осуществил свою мечту и всё такое.
                  Казалось бы глава Роснефти и один узбекский вор тут совершенно непричем...
                  Ответить
                  • А что, ему денег изначально сразу Сечин с Усмановым одолжили?

                    На самом деле я не вижу ничего постыдного в привлечении крупных денег в свой стартап. Ну Гейтс ведь тоже с контракта с IBM начинал;)

                    Хотя конечно компании вроде Яндекса, поднявшиеся изначально на качественных продуктах и своих ноу-хау -- такие компании вызывают у меня больше симпатии)
                    Ответить
                    • Яндекс довольно долго работал в убыток, на деньги от первой фирмы Воложа, продававшей железо. А потом было "привлечение крупных денег в свой стартап".
                      А компания и правда хорошая.
                      Ответить
                    • >ему денег изначально сразу Сечин с Усмановым одолжили
                      Там мутная история. Никто ж вам правду не скажет.
                      Может сначала его финансировали грузинский вор и один еврей.

                      Судить можно только по косвенным фактам - видя как быстро и умело пашу выперли на мороз можно догадаться какая его роль во всём этом.

                      Да и судя по тому что контакт не закрывали за пиратство и распространение прона у него явно были высокие покровители.
                      Ответить
            • > Олимпиадники тут ни при чем

              7 марта бывший замгендиректора «ВКонтакте» Илья Перекопский обвинил Дурова в предательстве, заявив, что тот «увёл в Telegram 15 лучших программистов-олимпиадников»
              http://tjournal.ru/paper/durov-country-contest

              ок, в следующий раз буду писать зелёным, раз без него не понятно.
              Ответить
              • Сарказмом там за километр несёт, но без этой новости непонятно над чем же именно так въедливо иронизируете: над взлетевшим vk или над telegram.
                Ответить
                • См. также
                  http://govnokod.ru/15406
                  Ответить
                  • Все! Я теперь все понял!

                    Проблема не в том что он увел олимпиадников, а в том что весь вконтакте состоит из тысяч маленьких программок на сях примерно такого вот уровня читаемости. И каждую програмку поддерживал ее автор (олимпиадник).

                    Теперь авторы ушли, и вконтакнт проще переписать, чем разобраться с существующим кодом_)
                    Ответить
              • Спасибо, теперь я знаю как стать миллионером.
                --Набираешь олмпиадников
                --PROFIT
                Ответить
                • Набираешь олмпиадников
                  Они уходят в Гугл
                  ?????
                  PROFIT
                  Ответить
                  • >Набираешь олмпиадников
                    >Они уходят в Гугл
                    Гугл объявляет банкротство и ты скупаешь их активы за бесценок?
                    Ответить
    • >В нашем отделе взяли олимпиадника. За ним не следили

      Сами виноваты, code review для чего придумали?
      Ответить

    Добавить комментарий